blob: 6f9334ba52a7183b5c72ea5d6455cbef071df6c8 [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Phil Nashc6535a02017-03-01 16:04:44 +00002 * Catch v1.8.1
3 * Generated: 2017-03-01 16:04:19.016511
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"
Phil Nash0952b762017-02-28 14:19:09 +000043
44 // For newer version we can use __Pragma to disable the warnings locally
45# if __GNUC__ == 4 && __GNUC_MINOR__ >= 4 && __GNUC_MINOR__ <= 7
46# pragma GCC diagnostic ignored "-Wparentheses"
47# endif
48
Phil Nasha806c3e2015-03-04 08:23:40 +000049# pragma GCC diagnostic push
50# pragma GCC diagnostic ignored "-Wpadded"
Phil Nash5bc030d2012-08-16 18:48:50 +010051#endif
Phil Nash576aff62014-12-21 00:21:23 +000052#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
53# define CATCH_IMPL
Phil Nashf9df35b2014-03-10 18:02:18 +000054#endif
55
Phil Nash576aff62014-12-21 00:21:23 +000056#ifdef CATCH_IMPL
Phil Nash9abb2762014-03-06 21:53:34 +000057# ifndef CLARA_CONFIG_MAIN
58# define CLARA_CONFIG_MAIN_NOT_DEFINED
59# define CLARA_CONFIG_MAIN
60# endif
61#endif
62
Phil Nash3b80af72012-08-09 07:47:30 +010063// #included from: internal/catch_notimplemented_exception.h
64#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010065
Phil Nash89d1e6c2011-05-24 08:23:02 +010066// #included from: catch_common.h
Phil Nash3b80af72012-08-09 07:47:30 +010067#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010068
Phil Nash8defc712013-04-24 19:10:02 +010069// #included from: catch_compiler_capabilities.h
70#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
71
Phil Nash318c9362015-05-19 18:40:00 +010072// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
73// The following features are defined:
74//
75// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
76// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
77// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
78// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
79// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
Phil Nash2f6371f2015-07-23 23:06:26 +010080// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
Phil Nashe73583d2015-08-07 17:30:34 +010081// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
Phil Nashd234ed12015-08-24 06:28:25 +010082// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010083// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported?
84// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported?
Phil Nash318c9362015-05-19 18:40:00 +010085
86// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
87
Phil Nash318c9362015-05-19 18:40:00 +010088// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
Phil Nashc984fc32016-03-15 07:24:26 +000089// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +010090// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
Phil Nash0952b762017-02-28 14:19:09 +000091// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
Phil Nashd234ed12015-08-24 06:28:25 +010092// ****************
93// Note to maintainers: if new toggles are added please document them
94// in configuration.md, too
95// ****************
96
Phil Nash3b18d9e2015-06-30 18:26:09 +010097// In general each macro has a _NO_<feature name> form
98// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
99// Many features, at point of detection, define an _INTERNAL_ macro, so they
100// can be combined, en-mass, with the _NO_ forms later.
101
102// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
Phil Nash8defc712013-04-24 19:10:02 +0100103
Phil Nashac220282016-06-09 08:19:23 +0100104#ifdef __cplusplus
105
106# if __cplusplus >= 201103L
107# define CATCH_CPP11_OR_GREATER
108# endif
109
110# if __cplusplus >= 201402L
111# define CATCH_CPP14_OR_GREATER
112# endif
113
Phil Nashae5ee2c2016-02-29 08:17:18 +0000114#endif
115
Phil Nash859760a2013-12-14 14:34:05 +0000116#ifdef __clang__
Phil Nash859760a2013-12-14 14:34:05 +0000117
Phil Nash17404952014-04-23 18:19:49 +0100118# if __has_feature(cxx_nullptr)
Phil Nash3b18d9e2015-06-30 18:26:09 +0100119# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
Phil Nash17404952014-04-23 18:19:49 +0100120# endif
Phil Nash859760a2013-12-14 14:34:05 +0000121
Phil Nash17404952014-04-23 18:19:49 +0100122# if __has_feature(cxx_noexcept)
Phil Nash3b18d9e2015-06-30 18:26:09 +0100123# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
Phil Nash17404952014-04-23 18:19:49 +0100124# endif
Phil Nash859760a2013-12-14 14:34:05 +0000125
Phil Nashae5ee2c2016-02-29 08:17:18 +0000126# if defined(CATCH_CPP11_OR_GREATER)
Phil Nash0952b762017-02-28 14:19:09 +0000127# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
128 _Pragma( "clang diagnostic push" ) \
129 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
130# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
131 _Pragma( "clang diagnostic pop" )
Phil Nashae5ee2c2016-02-29 08:17:18 +0000132# endif
133
Phil Nash859760a2013-12-14 14:34:05 +0000134#endif // __clang__
135
Phil Nash8defc712013-04-24 19:10:02 +0100136////////////////////////////////////////////////////////////////////////////////
Phil Nash0952b762017-02-28 14:19:09 +0000137// Cygwin
138#ifdef __CYGWIN__
139
140# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
141# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
142# endif
143
Phil Nashc6535a02017-03-01 16:04:44 +0000144// Required for some versions of Cygwin to declare gettimeofday
145// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
146# define _BSD_SOURCE
147
Phil Nash0952b762017-02-28 14:19:09 +0000148#endif // __CYGWIN__
149
150////////////////////////////////////////////////////////////////////////////////
Phil Nash8defc712013-04-24 19:10:02 +0100151// Borland
152#ifdef __BORLANDC__
153
Phil Nash8defc712013-04-24 19:10:02 +0100154#endif // __BORLANDC__
155
156////////////////////////////////////////////////////////////////////////////////
157// EDG
158#ifdef __EDG_VERSION__
159
Phil Nash8defc712013-04-24 19:10:02 +0100160#endif // __EDG_VERSION__
161
162////////////////////////////////////////////////////////////////////////////////
163// Digital Mars
164#ifdef __DMC__
165
Phil Nash8defc712013-04-24 19:10:02 +0100166#endif // __DMC__
167
168////////////////////////////////////////////////////////////////////////////////
169// GCC
170#ifdef __GNUC__
171
Phil Nash0952b762017-02-28 14:19:09 +0000172# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
173# define CATCH_GCC_HAS_NEW_PRAGMA
174# endif
175
Phil Nashae5ee2c2016-02-29 08:17:18 +0000176# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
177# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
178# endif
179
Phil Nash0952b762017-02-28 14:19:09 +0000180# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_GCC_HAS_NEW_PRAGMA)
181# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
182 _Pragma( "GCC diagnostic push" ) \
183 _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
184# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
185 _Pragma( "GCC diagnostic pop" )
Phil Nashae5ee2c2016-02-29 08:17:18 +0000186# endif
Phil Nash859760a2013-12-14 14:34:05 +0000187
Phil Nash8b1b7cd2015-08-03 07:40:52 +0100188// - otherwise more recent versions define __cplusplus >= 201103L
189// and will get picked up below
190
Phil Nash8defc712013-04-24 19:10:02 +0100191#endif // __GNUC__
192
193////////////////////////////////////////////////////////////////////////////////
194// Visual C++
195#ifdef _MSC_VER
196
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +0100197#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
198
Phil Nash43470b22015-05-19 22:37:23 +0100199#if (_MSC_VER >= 1600)
Phil Nash3b18d9e2015-06-30 18:26:09 +0100200# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
Phil Nashd234ed12015-08-24 06:28:25 +0100201# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
Phil Nash43470b22015-05-19 22:37:23 +0100202#endif
203
Phil Nash318c9362015-05-19 18:40:00 +0100204#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
Phil Nash3b18d9e2015-06-30 18:26:09 +0100205#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
206#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
Phil Nash3b2f2062017-01-11 16:43:56 +0000207#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100208#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
Phil Nash318c9362015-05-19 18:40:00 +0100209#endif
210
Phil Nash8defc712013-04-24 19:10:02 +0100211#endif // _MSC_VER
212
Phil Nashd234ed12015-08-24 06:28:25 +0100213////////////////////////////////////////////////////////////////////////////////
214
Phil Nash8defc712013-04-24 19:10:02 +0100215// Use variadic macros if the compiler supports them
216#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
217 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
218 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
219 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
Phil Nash786959d2013-06-07 19:07:50 +0100220
Phil Nash3b18d9e2015-06-30 18:26:09 +0100221#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
Phil Nash786959d2013-06-07 19:07:50 +0100222
Phil Nash8defc712013-04-24 19:10:02 +0100223#endif
224
Phil Nashc984fc32016-03-15 07:24:26 +0000225// Use __COUNTER__ if the compiler supports it
226#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
227 ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
228 ( defined __clang__ && __clang_major__ >= 3 )
229
230#define CATCH_INTERNAL_CONFIG_COUNTER
231
232#endif
233
Phil Nashd7e17902014-04-18 08:49:35 +0100234////////////////////////////////////////////////////////////////////////////////
235// C++ language feature support
236
Phil Nash318c9362015-05-19 18:40:00 +0100237// catch all support for C++11
Phil Nashae5ee2c2016-02-29 08:17:18 +0000238#if defined(CATCH_CPP11_OR_GREATER)
Phil Nash318c9362015-05-19 18:40:00 +0100239
Phil Nash3b18d9e2015-06-30 18:26:09 +0100240# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
241# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
Phil Nash318c9362015-05-19 18:40:00 +0100242# endif
243
Phil Nash3b18d9e2015-06-30 18:26:09 +0100244# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
245# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
Phil Nash318c9362015-05-19 18:40:00 +0100246# endif
247
Phil Nash3b18d9e2015-06-30 18:26:09 +0100248# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
249# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
Phil Nash318c9362015-05-19 18:40:00 +0100250# endif
251
Phil Nash3b18d9e2015-06-30 18:26:09 +0100252# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
253# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
Phil Nash318c9362015-05-19 18:40:00 +0100254# endif
255
Phil Nash3b18d9e2015-06-30 18:26:09 +0100256# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
257# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
Phil Nash318c9362015-05-19 18:40:00 +0100258# endif
259
Phil Nash3b18d9e2015-06-30 18:26:09 +0100260# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
261# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
Phil Nash318c9362015-05-19 18:40:00 +0100262# endif
263
Phil Nash2f6371f2015-07-23 23:06:26 +0100264# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
265# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
266# endif
267
Phil Nashe73583d2015-08-07 17:30:34 +0100268# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
269# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
270# endif
Phil Nashd234ed12015-08-24 06:28:25 +0100271# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
272# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
273# endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000274# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE)
275# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
276# endif
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100277# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS)
278# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
279# endif
Phil Nashe73583d2015-08-07 17:30:34 +0100280
Phil Nash318c9362015-05-19 18:40:00 +0100281#endif // __cplusplus >= 201103L
Phil Nashd7e17902014-04-18 08:49:35 +0100282
Phil Nash3b18d9e2015-06-30 18:26:09 +0100283// Now set the actual defines based on the above + anything the user has configured
284#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
285# define CATCH_CONFIG_CPP11_NULLPTR
286#endif
287#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
288# define CATCH_CONFIG_CPP11_NOEXCEPT
289#endif
290#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)
291# define CATCH_CONFIG_CPP11_GENERATED_METHODS
292#endif
293#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)
294# define CATCH_CONFIG_CPP11_IS_ENUM
295#endif
296#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
297# define CATCH_CONFIG_CPP11_TUPLE
298#endif
299#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 +0100300# define CATCH_CONFIG_VARIADIC_MACROS
301#endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000302#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 +0100303# define CATCH_CONFIG_CPP11_LONG_LONG
Phil Nash3b18d9e2015-06-30 18:26:09 +0100304#endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000305#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 +0100306# define CATCH_CONFIG_CPP11_OVERRIDE
307#endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000308#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 +0100309# define CATCH_CONFIG_CPP11_UNIQUE_PTR
Phil Nash3b18d9e2015-06-30 18:26:09 +0100310#endif
Martin Hořeňovský9a566092017-01-20 12:49:59 +0100311// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
312// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
313// This does not affect compilation
314#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 +0000315# define CATCH_CONFIG_COUNTER
316#endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000317#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
318# define CATCH_CONFIG_CPP11_SHUFFLE
319#endif
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100320# 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)
321# define CATCH_CONFIG_CPP11_TYPE_TRAITS
322# endif
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +0100323#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
324# define CATCH_CONFIG_WINDOWS_SEH
325#endif
Phil Nash0952b762017-02-28 14:19:09 +0000326// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
327#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
328# define CATCH_CONFIG_POSIX_SIGNALS
329#endif
Phil Nash3b18d9e2015-06-30 18:26:09 +0100330
Phil Nashae5ee2c2016-02-29 08:17:18 +0000331#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
332# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
Phil Nash0952b762017-02-28 14:19:09 +0000333# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
Phil Nashae5ee2c2016-02-29 08:17:18 +0000334#endif
335
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(); \
773 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
774 static void TestName()
Phil Nash93906752013-03-16 20:21:51 +0000775 #define INTERNAL_CATCH_TESTCASE( ... ) \
Phil Nashc984fc32016-03-15 07:24:26 +0000776 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 +0100777
Phil Nash93906752013-03-16 20:21:51 +0000778 ///////////////////////////////////////////////////////////////////////////////
Phil Nash93906752013-03-16 20:21:51 +0000779 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
780 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100781
Phil Nash93906752013-03-16 20:21:51 +0000782 ///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +0000783 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
Phil Nash93906752013-03-16 20:21:51 +0000784 namespace{ \
Phil Nashc984fc32016-03-15 07:24:26 +0000785 struct TestName : ClassName{ \
Phil Nash93906752013-03-16 20:21:51 +0000786 void test(); \
787 }; \
Phil Nashc984fc32016-03-15 07:24:26 +0000788 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
Phil Nash93906752013-03-16 20:21:51 +0000789 } \
Phil Nashc984fc32016-03-15 07:24:26 +0000790 void TestName::test()
791 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
792 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 +0100793
Phil Nash7e15d9b2015-11-20 16:59:14 +0000794 ///////////////////////////////////////////////////////////////////////////////
795 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
796 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
797
Phil Nash93906752013-03-16 20:21:51 +0000798#else
799 ///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +0000800 #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
801 static void TestName(); \
802 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
803 static void TestName()
Phil Nash93906752013-03-16 20:21:51 +0000804 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
Phil Nashc984fc32016-03-15 07:24:26 +0000805 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 +0000806
807 ///////////////////////////////////////////////////////////////////////////////
Phil Nash93906752013-03-16 20:21:51 +0000808 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
809 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
810
811 ///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +0000812 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
Phil Nash93906752013-03-16 20:21:51 +0000813 namespace{ \
Phil Nashc984fc32016-03-15 07:24:26 +0000814 struct TestCaseName : ClassName{ \
Phil Nash93906752013-03-16 20:21:51 +0000815 void test(); \
816 }; \
Phil Nashc984fc32016-03-15 07:24:26 +0000817 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
Phil Nash93906752013-03-16 20:21:51 +0000818 } \
Phil Nashc984fc32016-03-15 07:24:26 +0000819 void TestCaseName::test()
820 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
821 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 +0000822
Phil Nash7e15d9b2015-11-20 16:59:14 +0000823 ///////////////////////////////////////////////////////////////////////////////
824 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
825 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
Phil Nash93906752013-03-16 20:21:51 +0000826#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +0100827
828// #included from: internal/catch_capture.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100829#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100830
Phil Nashab036682014-06-02 07:48:03 +0100831// #included from: catch_result_builder.h
832#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
Phil Nash89d2a3f2012-05-16 15:09:17 +0100833
Phil Nash89d1e6c2011-05-24 08:23:02 +0100834// #included from: catch_result_type.h
Phil Nash3b80af72012-08-09 07:47:30 +0100835#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100836
Phil Nash89d2a3f2012-05-16 15:09:17 +0100837namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100838
Phil Nash90a35942012-11-13 22:04:29 +0000839 // ResultWas::OfType enum
840 struct ResultWas { enum OfType {
841 Unknown = -1,
842 Ok = 0,
843 Info = 1,
844 Warning = 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100845
Phil Nash90a35942012-11-13 22:04:29 +0000846 FailureBit = 0x10,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100847
Phil Nash90a35942012-11-13 22:04:29 +0000848 ExpressionFailed = FailureBit | 1,
849 ExplicitFailure = FailureBit | 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100850
Phil Nash90a35942012-11-13 22:04:29 +0000851 Exception = 0x100 | FailureBit,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100852
Phil Nash90a35942012-11-13 22:04:29 +0000853 ThrewException = Exception | 1,
Phil Nash93b61e12014-08-22 19:35:41 +0100854 DidntThrowException = Exception | 2,
855
856 FatalErrorCondition = 0x200 | FailureBit
Phil Nash89d1e6c2011-05-24 08:23:02 +0100857
Phil Nash90a35942012-11-13 22:04:29 +0000858 }; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100859
Phil Nash90a35942012-11-13 22:04:29 +0000860 inline bool isOk( ResultWas::OfType resultType ) {
861 return ( resultType & ResultWas::FailureBit ) == 0;
862 }
Phil Nasha2773812013-02-02 20:37:58 +0000863 inline bool isJustInfo( int flags ) {
864 return flags == ResultWas::Info;
865 }
Phil Nash67305122012-10-09 11:48:55 +0100866
Phil Nash90a35942012-11-13 22:04:29 +0000867 // ResultDisposition::Flags enum
868 struct ResultDisposition { enum Flags {
Phil Nash318c9362015-05-19 18:40:00 +0100869 Normal = 0x01,
Phil Nash90a35942012-11-13 22:04:29 +0000870
Phil Nash318c9362015-05-19 18:40:00 +0100871 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
872 FalseTest = 0x04, // Prefix expression with !
873 SuppressFail = 0x08 // Failures are reported but do not fail the test
Phil Nash90a35942012-11-13 22:04:29 +0000874 }; };
875
876 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
877 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
878 }
879
Phil Nash3e2e3182012-11-17 10:49:24 +0000880 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
Phil Nashab036682014-06-02 07:48:03 +0100881 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
Phil Nash3e2e3182012-11-17 10:49:24 +0000882 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
Phil Nash90a35942012-11-13 22:04:29 +0000883
884} // end namespace Catch
Phil Nash89d1e6c2011-05-24 08:23:02 +0100885
Phil Nashab036682014-06-02 07:48:03 +0100886// #included from: catch_assertionresult.h
887#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
888
889#include <string>
Phil Nash89d1e6c2011-05-24 08:23:02 +0100890
Phil Nash89d2a3f2012-05-16 15:09:17 +0100891namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100892
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100893 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
894
895 struct DecomposedExpression
896 {
897 virtual ~DecomposedExpression() {}
898 virtual bool isBinaryExpression() const {
899 return false;
900 }
901 virtual void reconstructExpression( std::string& dest ) const = 0;
902
903 // Only simple binary comparisons can be decomposed.
904 // If more complex check is required then wrap sub-expressions in parentheses.
905 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& );
906 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& );
907 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& );
908 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& );
909 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& );
910 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& );
911 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& );
Phil Nash0952b762017-02-28 14:19:09 +0000912
913 private:
914 DecomposedExpression& operator = (DecomposedExpression const&);
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100915 };
916
Phil Nashce612bf2012-11-01 08:27:09 +0000917 struct AssertionInfo
Phil Nash67305122012-10-09 11:48:55 +0100918 {
Phil Nashce612bf2012-11-01 08:27:09 +0000919 AssertionInfo() {}
Phil Nash8defc712013-04-24 19:10:02 +0100920 AssertionInfo( std::string const& _macroName,
921 SourceLineInfo const& _lineInfo,
922 std::string const& _capturedExpression,
Phil Nash90a35942012-11-13 22:04:29 +0000923 ResultDisposition::Flags _resultDisposition );
Phil Nash67305122012-10-09 11:48:55 +0100924
925 std::string macroName;
926 SourceLineInfo lineInfo;
927 std::string capturedExpression;
Phil Nash90a35942012-11-13 22:04:29 +0000928 ResultDisposition::Flags resultDisposition;
Phil Nashce612bf2012-11-01 08:27:09 +0000929 };
930
931 struct AssertionResultData
932 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100933 AssertionResultData() : decomposedExpression( CATCH_NULL )
934 , resultType( ResultWas::Unknown )
935 , negated( false )
936 , parenthesized( false ) {}
Phil Nashce612bf2012-11-01 08:27:09 +0000937
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100938 void negate( bool parenthesize ) {
939 negated = !negated;
940 parenthesized = parenthesize;
941 if( resultType == ResultWas::Ok )
942 resultType = ResultWas::ExpressionFailed;
943 else if( resultType == ResultWas::ExpressionFailed )
944 resultType = ResultWas::Ok;
945 }
946
947 std::string const& reconstructExpression() const {
948 if( decomposedExpression != CATCH_NULL ) {
949 decomposedExpression->reconstructExpression( reconstructedExpression );
950 if( parenthesized ) {
951 reconstructedExpression.insert( 0, 1, '(' );
952 reconstructedExpression.append( 1, ')' );
953 }
954 if( negated ) {
955 reconstructedExpression.insert( 0, 1, '!' );
956 }
957 decomposedExpression = CATCH_NULL;
958 }
959 return reconstructedExpression;
960 }
961
962 mutable DecomposedExpression const* decomposedExpression;
963 mutable std::string reconstructedExpression;
Phil Nash67305122012-10-09 11:48:55 +0100964 std::string message;
965 ResultWas::OfType resultType;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100966 bool negated;
967 bool parenthesized;
Phil Nash67305122012-10-09 11:48:55 +0100968 };
969
Phil Nashce612bf2012-11-01 08:27:09 +0000970 class AssertionResult {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100971 public:
Phil Nashce612bf2012-11-01 08:27:09 +0000972 AssertionResult();
Phil Nash8defc712013-04-24 19:10:02 +0100973 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
Phil Nashce612bf2012-11-01 08:27:09 +0000974 ~AssertionResult();
Phil Nash318c9362015-05-19 18:40:00 +0100975# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +0100976 AssertionResult( AssertionResult const& ) = default;
977 AssertionResult( AssertionResult && ) = default;
978 AssertionResult& operator = ( AssertionResult const& ) = default;
979 AssertionResult& operator = ( AssertionResult && ) = default;
980# endif
Phil Nash89d1e6c2011-05-24 08:23:02 +0100981
Phil Nash90a35942012-11-13 22:04:29 +0000982 bool isOk() const;
983 bool succeeded() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100984 ResultWas::OfType getResultType() const;
985 bool hasExpression() const;
986 bool hasMessage() const;
987 std::string getExpression() const;
Phil Nash786959d2013-06-07 19:07:50 +0100988 std::string getExpressionInMacro() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100989 bool hasExpandedExpression() const;
990 std::string getExpandedExpression() const;
991 std::string getMessage() const;
Phil Nashce612bf2012-11-01 08:27:09 +0000992 SourceLineInfo getSourceInfo() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100993 std::string getTestMacroName() const;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100994 void discardDecomposedExpression() const;
995 void expandDecomposedExpression() const;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100996
997 protected:
Phil Nashce612bf2012-11-01 08:27:09 +0000998 AssertionInfo m_info;
999 AssertionResultData m_resultData;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001000 };
1001
1002} // end namespace Catch
1003
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001004// #included from: catch_matchers.hpp
1005#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
1006
1007namespace Catch {
1008namespace Matchers {
1009 namespace Impl {
1010
Phil Nash0952b762017-02-28 14:19:09 +00001011 template<typename ArgT> struct MatchAllOf;
1012 template<typename ArgT> struct MatchAnyOf;
1013 template<typename ArgT> struct MatchNotOf;
Phil Nash08844e72015-11-05 18:52:18 +00001014
Phil Nash0952b762017-02-28 14:19:09 +00001015 class MatcherUntypedBase {
Phil Nash92356762015-11-06 18:06:56 +00001016 public:
Phil Nash0952b762017-02-28 14:19:09 +00001017 std::string toString() const {
1018 if( m_cachedToString.empty() )
1019 m_cachedToString = describe();
1020 return m_cachedToString;
Phil Nashd234ed12015-08-24 06:28:25 +01001021 }
1022
Phil Nash0952b762017-02-28 14:19:09 +00001023 protected:
1024 virtual std::string describe() const = 0;
1025 mutable std::string m_cachedToString;
Phil Nash92356762015-11-06 18:06:56 +00001026 private:
Phil Nash0952b762017-02-28 14:19:09 +00001027 MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
Phil Nashd234ed12015-08-24 06:28:25 +01001028 };
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001029
Phil Nash0952b762017-02-28 14:19:09 +00001030 template<typename ObjectT, typename ComparatorT = ObjectT>
1031 struct MatcherBase : MatcherUntypedBase {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001032
Phil Nash0952b762017-02-28 14:19:09 +00001033 virtual bool match( ObjectT const& arg ) const = 0;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001034
Phil Nash0952b762017-02-28 14:19:09 +00001035 MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const;
1036 MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
1037 MatchNotOf<ComparatorT> operator ! () const;
1038 };
1039
1040 template<typename ArgT>
1041 struct MatchAllOf : MatcherBase<ArgT> {
1042 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
1043 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1044 if (!m_matchers[i]->match(arg))
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001045 return false;
Phil Nash0952b762017-02-28 14:19:09 +00001046 }
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001047 return true;
1048 }
Phil Nash0952b762017-02-28 14:19:09 +00001049 virtual std::string describe() const CATCH_OVERRIDE {
1050 std::string description;
1051 description.reserve( 4 + m_matchers.size()*32 );
1052 description += "( ";
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001053 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1054 if( i != 0 )
Phil Nash0952b762017-02-28 14:19:09 +00001055 description += " and ";
1056 description += m_matchers[i]->toString();
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001057 }
Phil Nash0952b762017-02-28 14:19:09 +00001058 description += " )";
1059 return description;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001060 }
1061
Phil Nash0952b762017-02-28 14:19:09 +00001062 MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
1063 m_matchers.push_back( &other );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001064 return *this;
1065 }
Phil Nash0952b762017-02-28 14:19:09 +00001066
1067 std::vector<MatcherBase<ArgT> const*> m_matchers;
1068 };
1069 template<typename ArgT>
1070 struct MatchAnyOf : MatcherBase<ArgT> {
1071
1072 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
1073 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1074 if (m_matchers[i]->match(arg))
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001075 return true;
Phil Nash0952b762017-02-28 14:19:09 +00001076 }
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001077 return false;
1078 }
Phil Nash0952b762017-02-28 14:19:09 +00001079 virtual std::string describe() const CATCH_OVERRIDE {
1080 std::string description;
1081 description.reserve( 4 + m_matchers.size()*32 );
1082 description += "( ";
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001083 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1084 if( i != 0 )
Phil Nash0952b762017-02-28 14:19:09 +00001085 description += " or ";
1086 description += m_matchers[i]->toString();
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001087 }
Phil Nash0952b762017-02-28 14:19:09 +00001088 description += " )";
1089 return description;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001090 }
1091
Phil Nash0952b762017-02-28 14:19:09 +00001092 MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
1093 m_matchers.push_back( &other );
1094 return *this;
Phil Nash08844e72015-11-05 18:52:18 +00001095 }
1096
Phil Nash0952b762017-02-28 14:19:09 +00001097 std::vector<MatcherBase<ArgT> const*> m_matchers;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001098 };
Phil Nash08844e72015-11-05 18:52:18 +00001099
Phil Nash0952b762017-02-28 14:19:09 +00001100 template<typename ArgT>
1101 struct MatchNotOf : MatcherBase<ArgT> {
Phil Nash08844e72015-11-05 18:52:18 +00001102
Phil Nash0952b762017-02-28 14:19:09 +00001103 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
Phil Nash08844e72015-11-05 18:52:18 +00001104
Phil Nash0952b762017-02-28 14:19:09 +00001105 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
1106 return !m_underlyingMatcher.match( arg );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001107 }
Phil Nash0952b762017-02-28 14:19:09 +00001108
1109 virtual std::string describe() const CATCH_OVERRIDE {
1110 return "not " + m_underlyingMatcher.toString();
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001111 }
Phil Nash0952b762017-02-28 14:19:09 +00001112 MatcherBase<ArgT> const& m_underlyingMatcher;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001113 };
1114
Phil Nash0952b762017-02-28 14:19:09 +00001115 template<typename ObjectT, typename ComparatorT>
1116 MatchAllOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator && ( MatcherBase const& other ) const {
1117 return MatchAllOf<ComparatorT>() && *this && other;
1118 }
1119 template<typename ObjectT, typename ComparatorT>
1120 MatchAnyOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator || ( MatcherBase const& other ) const {
1121 return MatchAnyOf<ComparatorT>() || *this || other;
1122 }
1123 template<typename ObjectT, typename ComparatorT>
1124 MatchNotOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator ! () const {
1125 return MatchNotOf<ComparatorT>( *this );
1126 }
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001127
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001128 } // namespace Impl
1129
1130 // The following functions create the actual matcher objects.
1131 // This allows the types to be inferred
Phil Nash0952b762017-02-28 14:19:09 +00001132 // - deprecated: prefer ||, && and !
1133 template<typename T>
1134 inline Impl::MatchNotOf<T> Not( Impl::MatcherBase<T> const& underlyingMatcher ) {
1135 return Impl::MatchNotOf<T>( underlyingMatcher );
Phil Nashd234ed12015-08-24 06:28:25 +01001136 }
Phil Nash0952b762017-02-28 14:19:09 +00001137 template<typename T>
1138 inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
1139 return Impl::MatchAllOf<T>() && m1 && m2;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001140 }
Phil Nash0952b762017-02-28 14:19:09 +00001141 template<typename T>
1142 inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
1143 return Impl::MatchAllOf<T>() && m1 && m2 && m3;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001144 }
Phil Nash0952b762017-02-28 14:19:09 +00001145 template<typename T>
1146 inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
1147 return Impl::MatchAnyOf<T>() || m1 || m2;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001148 }
Phil Nash0952b762017-02-28 14:19:09 +00001149 template<typename T>
1150 inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
1151 return Impl::MatchAnyOf<T>() || m1 || m2 || m3;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001152 }
1153
1154} // namespace Matchers
1155
1156using namespace Matchers;
Phil Nash0952b762017-02-28 14:19:09 +00001157using Matchers::Impl::MatcherBase;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001158
1159} // namespace Catch
1160
Phil Nashab036682014-06-02 07:48:03 +01001161namespace Catch {
1162
1163 struct TestFailureException{};
1164
1165 template<typename T> class ExpressionLhs;
1166
Phil Nashab036682014-06-02 07:48:03 +01001167 struct CopyableStream {
1168 CopyableStream() {}
1169 CopyableStream( CopyableStream const& other ) {
1170 oss << other.oss.str();
1171 }
1172 CopyableStream& operator=( CopyableStream const& other ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001173 oss.str(std::string());
Phil Nashab036682014-06-02 07:48:03 +01001174 oss << other.oss.str();
1175 return *this;
1176 }
1177 std::ostringstream oss;
1178 };
1179
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001180 class ResultBuilder : public DecomposedExpression {
Phil Nashab036682014-06-02 07:48:03 +01001181 public:
1182 ResultBuilder( char const* macroName,
1183 SourceLineInfo const& lineInfo,
1184 char const* capturedExpression,
Phil Nash93a842e2015-07-13 06:36:07 +01001185 ResultDisposition::Flags resultDisposition,
1186 char const* secondArg = "" );
Phil Nashab036682014-06-02 07:48:03 +01001187
1188 template<typename T>
Phil Nash21f7ef62015-06-29 18:05:23 +01001189 ExpressionLhs<T const&> operator <= ( T const& operand );
1190 ExpressionLhs<bool> operator <= ( bool value );
Phil Nashab036682014-06-02 07:48:03 +01001191
1192 template<typename T>
1193 ResultBuilder& operator << ( T const& value ) {
1194 m_stream.oss << value;
1195 return *this;
1196 }
1197
Phil Nashab036682014-06-02 07:48:03 +01001198 ResultBuilder& setResultType( ResultWas::OfType result );
1199 ResultBuilder& setResultType( bool result );
Phil Nashab036682014-06-02 07:48:03 +01001200
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001201 void endExpression( DecomposedExpression const& expr );
Phil Nashab036682014-06-02 07:48:03 +01001202
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001203 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE;
1204
Phil Nashab036682014-06-02 07:48:03 +01001205 AssertionResult build() const;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001206 AssertionResult build( DecomposedExpression const& expr ) const;
Phil Nashab036682014-06-02 07:48:03 +01001207
1208 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
1209 void captureResult( ResultWas::OfType resultType );
1210 void captureExpression();
Phil Nash93a842e2015-07-13 06:36:07 +01001211 void captureExpectedException( std::string const& expectedMessage );
Phil Nash0952b762017-02-28 14:19:09 +00001212 void captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher );
Phil Nash93a842e2015-07-13 06:36:07 +01001213 void handleResult( AssertionResult const& result );
Phil Nashab036682014-06-02 07:48:03 +01001214 void react();
1215 bool shouldDebugBreak() const;
1216 bool allowThrows() const;
1217
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001218 template<typename ArgT, typename MatcherT>
1219 void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString );
1220
Phil Nashab036682014-06-02 07:48:03 +01001221 private:
1222 AssertionInfo m_assertionInfo;
1223 AssertionResultData m_data;
Phil Nashab036682014-06-02 07:48:03 +01001224 CopyableStream m_stream;
1225
1226 bool m_shouldDebugBreak;
1227 bool m_shouldThrow;
1228 };
1229
1230} // namespace Catch
1231
1232// Include after due to circular dependency:
1233// #included from: catch_expression_lhs.hpp
1234#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1235
Phil Nash89d1e6c2011-05-24 08:23:02 +01001236// #included from: catch_evaluate.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001237#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001238
Phil Nashdd26e882013-03-25 09:25:31 +00001239#ifdef _MSC_VER
1240#pragma warning(push)
1241#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
Phil Nash0952b762017-02-28 14:19:09 +00001242#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
Phil Nashdd26e882013-03-25 09:25:31 +00001243#endif
1244
Phil Nash17404952014-04-23 18:19:49 +01001245#include <cstddef>
1246
Phil Nash89d2a3f2012-05-16 15:09:17 +01001247namespace Catch {
1248namespace Internal {
1249
1250 enum Operator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001251 IsEqualTo,
1252 IsNotEqualTo,
1253 IsLessThan,
1254 IsGreaterThan,
1255 IsLessThanOrEqualTo,
1256 IsGreaterThanOrEqualTo
1257 };
1258
Phil Nash371db8b2012-05-21 18:52:09 +01001259 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
1260 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
1261 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
1262 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
1263 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
1264 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
1265 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
Phil Nash89d1e6c2011-05-24 08:23:02 +01001266
Phil Nash471eba22013-04-22 18:55:12 +01001267 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01001268 inline T& opCast(T const& t) { return const_cast<T&>(t); }
Phil Nash471eba22013-04-22 18:55:12 +01001269
1270// nullptr_t support based on pull request #154 from Konstantin Baumann
1271#ifdef CATCH_CONFIG_CPP11_NULLPTR
1272 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1273#endif // CATCH_CONFIG_CPP11_NULLPTR
1274
Phil Nash89d1e6c2011-05-24 08:23:02 +01001275 // So the compare overloads can be operator agnostic we convey the operator as a template
1276 // enum, which is used to specialise an Evaluator for doing the comparison.
1277 template<typename T1, typename T2, Operator Op>
1278 class Evaluator{};
1279
1280 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001281 struct Evaluator<T1, T2, IsEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001282 static bool evaluate( T1 const& lhs, T2 const& rhs) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001283 return bool( opCast( lhs ) == opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001284 }
1285 };
1286 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001287 struct Evaluator<T1, T2, IsNotEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001288 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001289 return bool( opCast( lhs ) != opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001290 }
1291 };
1292 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001293 struct Evaluator<T1, T2, IsLessThan> {
Phil Nash8defc712013-04-24 19:10:02 +01001294 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001295 return bool( opCast( lhs ) < opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001296 }
1297 };
1298 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001299 struct Evaluator<T1, T2, IsGreaterThan> {
Phil Nash8defc712013-04-24 19:10:02 +01001300 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001301 return bool( opCast( lhs ) > opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001302 }
1303 };
1304 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001305 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001306 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001307 return bool( opCast( lhs ) >= opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001308 }
1309 };
1310 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001311 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
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
1317 template<Operator Op, typename T1, typename T2>
Phil Nash8defc712013-04-24 19:10:02 +01001318 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001319 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1320 }
1321
Phil Nash90a35942012-11-13 22:04:29 +00001322 // This level of indirection allows us to specialise for integer types
1323 // to avoid signed/ unsigned warnings
1324
Phil Nash89d1e6c2011-05-24 08:23:02 +01001325 // "base" overload
1326 template<Operator Op, typename T1, typename T2>
Phil Nash8defc712013-04-24 19:10:02 +01001327 bool compare( T1 const& lhs, T2 const& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001328 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1329 }
1330
1331 // unsigned X to int
Phil Nash89d2a3f2012-05-16 15:09:17 +01001332 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001333 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1334 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001335 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001336 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1337 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001338 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001339 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1340 }
1341
1342 // unsigned X to long
Phil Nash89d2a3f2012-05-16 15:09:17 +01001343 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001344 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1345 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001346 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001347 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1348 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001349 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001350 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1351 }
1352
1353 // int to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +01001354 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001355 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1356 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001357 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001358 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1359 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001360 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001361 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1362 }
1363
1364 // long to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +01001365 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001366 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001367 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001368 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001369 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001370 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001371 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001372 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001373 }
1374
Phil Nash06e959b2012-05-25 08:52:05 +01001375 // pointer to long (when comparing against NULL)
Phil Nash90a35942012-11-13 22:04:29 +00001376 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001377 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
Phil Nash6f1543b2012-05-07 19:46:19 +01001378 }
Phil Nash90a35942012-11-13 22:04:29 +00001379 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +01001380 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001381 }
1382
Phil Nash06e959b2012-05-25 08:52:05 +01001383 // pointer to int (when comparing against NULL)
Phil Nash90a35942012-11-13 22:04:29 +00001384 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +01001385 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1386 }
Phil Nash90a35942012-11-13 22:04:29 +00001387 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +01001388 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1389 }
1390
Phil Nash2f6371f2015-07-23 23:06:26 +01001391#ifdef CATCH_CONFIG_CPP11_LONG_LONG
1392 // long long to unsigned X
1393 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
1394 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1395 }
1396 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
1397 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1398 }
1399 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
1400 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1401 }
1402 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
1403 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1404 }
1405
1406 // unsigned long long to X
1407 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
1408 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1409 }
1410 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
1411 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1412 }
1413 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
1414 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1415 }
1416 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
1417 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1418 }
1419
1420 // pointer to long long (when comparing against NULL)
1421 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
1422 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1423 }
1424 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
1425 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1426 }
1427#endif // CATCH_CONFIG_CPP11_LONG_LONG
1428
Phil Nash471eba22013-04-22 18:55:12 +01001429#ifdef CATCH_CONFIG_CPP11_NULLPTR
1430 // pointer to nullptr_t (when comparing against nullptr)
1431 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01001432 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
Phil Nash471eba22013-04-22 18:55:12 +01001433 }
1434 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01001435 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
Phil Nash471eba22013-04-22 18:55:12 +01001436 }
1437#endif // CATCH_CONFIG_CPP11_NULLPTR
1438
Phil Nash89d1e6c2011-05-24 08:23:02 +01001439} // end of namespace Internal
1440} // end of namespace Catch
1441
Phil Nashdd26e882013-03-25 09:25:31 +00001442#ifdef _MSC_VER
1443#pragma warning(pop)
1444#endif
1445
Phil Nashab036682014-06-02 07:48:03 +01001446// #included from: catch_tostring.h
1447#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1448
Phil Nashab036682014-06-02 07:48:03 +01001449#include <sstream>
1450#include <iomanip>
1451#include <limits>
1452#include <vector>
1453#include <cstddef>
1454
1455#ifdef __OBJC__
1456// #included from: catch_objc_arc.hpp
1457#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1458
1459#import <Foundation/Foundation.h>
1460
1461#ifdef __has_feature
1462#define CATCH_ARC_ENABLED __has_feature(objc_arc)
1463#else
1464#define CATCH_ARC_ENABLED 0
1465#endif
1466
1467void arcSafeRelease( NSObject* obj );
1468id performOptionalSelector( id obj, SEL sel );
1469
1470#if !CATCH_ARC_ENABLED
1471inline void arcSafeRelease( NSObject* obj ) {
1472 [obj release];
1473}
1474inline id performOptionalSelector( id obj, SEL sel ) {
1475 if( [obj respondsToSelector: sel] )
1476 return [obj performSelector: sel];
1477 return nil;
1478}
1479#define CATCH_UNSAFE_UNRETAINED
1480#define CATCH_ARC_STRONG
1481#else
1482inline void arcSafeRelease( NSObject* ){}
1483inline id performOptionalSelector( id obj, SEL sel ) {
1484#ifdef __clang__
1485#pragma clang diagnostic push
1486#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1487#endif
1488 if( [obj respondsToSelector: sel] )
1489 return [obj performSelector: sel];
1490#ifdef __clang__
1491#pragma clang diagnostic pop
1492#endif
1493 return nil;
1494}
1495#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1496#define CATCH_ARC_STRONG __strong
1497#endif
1498
1499#endif
1500
Phil Nash318c9362015-05-19 18:40:00 +01001501#ifdef CATCH_CONFIG_CPP11_TUPLE
Phil Nash7f561522014-12-30 18:47:29 +00001502#include <tuple>
Phil Nash318c9362015-05-19 18:40:00 +01001503#endif
1504
1505#ifdef CATCH_CONFIG_CPP11_IS_ENUM
Phil Nash7f561522014-12-30 18:47:29 +00001506#include <type_traits>
1507#endif
1508
Phil Nashab036682014-06-02 07:48:03 +01001509namespace Catch {
Phil Nash4caabfa2014-09-03 19:23:22 +01001510
1511// Why we're here.
1512template<typename T>
1513std::string toString( T const& value );
1514
Phil Nash7f561522014-12-30 18:47:29 +00001515// Built in overloads
1516
1517std::string toString( std::string const& value );
1518std::string toString( std::wstring const& value );
1519std::string toString( const char* const value );
1520std::string toString( char* const value );
1521std::string toString( const wchar_t* const value );
1522std::string toString( wchar_t* const value );
1523std::string toString( int value );
1524std::string toString( unsigned long value );
1525std::string toString( unsigned int value );
1526std::string toString( const double value );
1527std::string toString( const float value );
1528std::string toString( bool value );
1529std::string toString( char value );
1530std::string toString( signed char value );
1531std::string toString( unsigned char value );
1532
Phil Nash2f6371f2015-07-23 23:06:26 +01001533#ifdef CATCH_CONFIG_CPP11_LONG_LONG
1534std::string toString( long long value );
1535std::string toString( unsigned long long value );
1536#endif
1537
Phil Nash7f561522014-12-30 18:47:29 +00001538#ifdef CATCH_CONFIG_CPP11_NULLPTR
1539std::string toString( std::nullptr_t );
1540#endif
1541
1542#ifdef __OBJC__
1543 std::string toString( NSString const * const& nsstring );
1544 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
1545 std::string toString( NSObject* const& nsObject );
1546#endif
1547
Phil Nashab036682014-06-02 07:48:03 +01001548namespace Detail {
1549
Phil Nash2f6371f2015-07-23 23:06:26 +01001550 extern const std::string unprintableString;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001551
Phil Nashab036682014-06-02 07:48:03 +01001552 struct BorgType {
1553 template<typename T> BorgType( T const& );
1554 };
1555
Phil Nash3b18d9e2015-06-30 18:26:09 +01001556 struct TrueType { char sizer[1]; };
1557 struct FalseType { char sizer[2]; };
1558
Phil Nashab036682014-06-02 07:48:03 +01001559 TrueType& testStreamable( std::ostream& );
1560 FalseType testStreamable( FalseType );
1561
1562 FalseType operator<<( std::ostream const&, BorgType const& );
1563
1564 template<typename T>
1565 struct IsStreamInsertable {
1566 static std::ostream &s;
1567 static T const&t;
1568 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
1569 };
1570
Phil Nash318c9362015-05-19 18:40:00 +01001571#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
Phil Nash4caabfa2014-09-03 19:23:22 +01001572 template<typename T,
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001573 bool IsEnum = std::is_enum<T>::value
Phil Nash4caabfa2014-09-03 19:23:22 +01001574 >
1575 struct EnumStringMaker
1576 {
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001577 static std::string convert( T const& ) { return unprintableString; }
Phil Nash4caabfa2014-09-03 19:23:22 +01001578 };
1579
1580 template<typename T>
1581 struct EnumStringMaker<T,true>
1582 {
1583 static std::string convert( T const& v )
1584 {
1585 return ::Catch::toString(
1586 static_cast<typename std::underlying_type<T>::type>(v)
1587 );
1588 }
1589 };
1590#endif
Phil Nashab036682014-06-02 07:48:03 +01001591 template<bool C>
1592 struct StringMakerBase {
Phil Nash318c9362015-05-19 18:40:00 +01001593#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
Phil Nash4caabfa2014-09-03 19:23:22 +01001594 template<typename T>
1595 static std::string convert( T const& v )
1596 {
1597 return EnumStringMaker<T>::convert( v );
1598 }
1599#else
Phil Nashab036682014-06-02 07:48:03 +01001600 template<typename T>
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001601 static std::string convert( T const& ) { return unprintableString; }
Phil Nash4caabfa2014-09-03 19:23:22 +01001602#endif
Phil Nashab036682014-06-02 07:48:03 +01001603 };
1604
1605 template<>
1606 struct StringMakerBase<true> {
1607 template<typename T>
1608 static std::string convert( T const& _value ) {
1609 std::ostringstream oss;
1610 oss << _value;
1611 return oss.str();
1612 }
1613 };
1614
1615 std::string rawMemoryToString( const void *object, std::size_t size );
1616
1617 template<typename T>
1618 inline std::string rawMemoryToString( const T& object ) {
1619 return rawMemoryToString( &object, sizeof(object) );
Phil Nash67305122012-10-09 11:48:55 +01001620 }
1621
Phil Nashab036682014-06-02 07:48:03 +01001622} // end namespace Detail
Phil Nashce612bf2012-11-01 08:27:09 +00001623
Phil Nashab036682014-06-02 07:48:03 +01001624template<typename T>
Phil Nashab036682014-06-02 07:48:03 +01001625struct StringMaker :
1626 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
Phil Nashcd688302013-06-29 12:11:32 +01001627
Phil Nashab036682014-06-02 07:48:03 +01001628template<typename T>
1629struct StringMaker<T*> {
1630 template<typename U>
1631 static std::string convert( U* p ) {
1632 if( !p )
Phil Nashb971fe72015-07-02 08:21:38 +01001633 return "NULL";
Phil Nashab036682014-06-02 07:48:03 +01001634 else
1635 return Detail::rawMemoryToString( p );
1636 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001637};
1638
Phil Nashab036682014-06-02 07:48:03 +01001639template<typename R, typename C>
1640struct StringMaker<R C::*> {
1641 static std::string convert( R C::* p ) {
1642 if( !p )
Phil Nashb971fe72015-07-02 08:21:38 +01001643 return "NULL";
Phil Nashab036682014-06-02 07:48:03 +01001644 else
1645 return Detail::rawMemoryToString( p );
1646 }
1647};
1648
1649namespace Detail {
1650 template<typename InputIterator>
1651 std::string rangeToString( InputIterator first, InputIterator last );
1652}
1653
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001654//template<typename T, typename Allocator>
1655//struct StringMaker<std::vector<T, Allocator> > {
1656// static std::string convert( std::vector<T,Allocator> const& v ) {
1657// return Detail::rangeToString( v.begin(), v.end() );
1658// }
1659//};
1660
Phil Nashab036682014-06-02 07:48:03 +01001661template<typename T, typename Allocator>
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001662std::string toString( std::vector<T,Allocator> const& v ) {
1663 return Detail::rangeToString( v.begin(), v.end() );
1664}
Phil Nashab036682014-06-02 07:48:03 +01001665
Phil Nash318c9362015-05-19 18:40:00 +01001666#ifdef CATCH_CONFIG_CPP11_TUPLE
Phil Nash572911d2015-03-04 18:33:31 +00001667
1668// toString for tuples
Phil Nash7f561522014-12-30 18:47:29 +00001669namespace TupleDetail {
1670 template<
1671 typename Tuple,
1672 std::size_t N = 0,
1673 bool = (N < std::tuple_size<Tuple>::value)
1674 >
1675 struct ElementPrinter {
1676 static void print( const Tuple& tuple, std::ostream& os )
1677 {
1678 os << ( N ? ", " : " " )
1679 << Catch::toString(std::get<N>(tuple));
1680 ElementPrinter<Tuple,N+1>::print(tuple,os);
1681 }
1682 };
1683
1684 template<
1685 typename Tuple,
1686 std::size_t N
1687 >
1688 struct ElementPrinter<Tuple,N,false> {
1689 static void print( const Tuple&, std::ostream& ) {}
1690 };
1691
1692}
1693
1694template<typename ...Types>
1695struct StringMaker<std::tuple<Types...>> {
1696
1697 static std::string convert( const std::tuple<Types...>& tuple )
1698 {
1699 std::ostringstream os;
1700 os << '{';
1701 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1702 os << " }";
1703 return os.str();
1704 }
1705};
Phil Nash318c9362015-05-19 18:40:00 +01001706#endif // CATCH_CONFIG_CPP11_TUPLE
Phil Nash7f561522014-12-30 18:47:29 +00001707
Phil Nashab036682014-06-02 07:48:03 +01001708namespace Detail {
1709 template<typename T>
1710 std::string makeString( T const& value ) {
1711 return StringMaker<T>::convert( value );
1712 }
1713} // end namespace Detail
1714
1715/// \brief converts any type to a string
1716///
1717/// The default template forwards on to ostringstream - except when an
1718/// ostringstream overload does not exist - in which case it attempts to detect
1719/// that and writes {?}.
1720/// Overload (not specialise) this template for custom typs that you don't want
1721/// to provide an ostream overload for.
1722template<typename T>
1723std::string toString( T const& value ) {
1724 return StringMaker<T>::convert( value );
1725}
1726
Phil Nashab036682014-06-02 07:48:03 +01001727 namespace Detail {
1728 template<typename InputIterator>
1729 std::string rangeToString( InputIterator first, InputIterator last ) {
1730 std::ostringstream oss;
1731 oss << "{ ";
1732 if( first != last ) {
Phil Nash13f98432014-12-12 08:11:18 +00001733 oss << Catch::toString( *first );
1734 for( ++first ; first != last ; ++first )
1735 oss << ", " << Catch::toString( *first );
Phil Nashab036682014-06-02 07:48:03 +01001736 }
1737 oss << " }";
1738 return oss.str();
1739 }
1740}
1741
Phil Nashd31737f2012-05-09 19:04:00 +01001742} // end namespace Catch
1743
Phil Nash89d2a3f2012-05-16 15:09:17 +01001744namespace Catch {
Phil Nash176eb812012-05-11 08:17:16 +01001745
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001746template<typename LhsT, Internal::Operator Op, typename RhsT>
1747class BinaryExpression;
Phil Nash176eb812012-05-11 08:17:16 +01001748
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001749template<typename ArgT, typename MatcherT>
1750class MatchExpression;
1751
1752// Wraps the LHS of an expression and overloads comparison operators
1753// for also capturing those and RHS (if any)
1754template<typename T>
1755class ExpressionLhs : public DecomposedExpression {
Phil Nash176eb812012-05-11 08:17:16 +01001756public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001757 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
Phil Nash176eb812012-05-11 08:17:16 +01001758
Phil Nash0952b762017-02-28 14:19:09 +00001759 ExpressionLhs& operator = ( const ExpressionLhs& );
1760
Phil Nash176eb812012-05-11 08:17:16 +01001761 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001762 BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001763 operator == ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001764 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001765 }
1766
1767 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001768 BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001769 operator != ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001770 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001771 }
1772
1773 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001774 BinaryExpression<T, Internal::IsLessThan, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001775 operator < ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001776 return captureExpression<Internal::IsLessThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001777 }
1778
1779 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001780 BinaryExpression<T, Internal::IsGreaterThan, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001781 operator > ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001782 return captureExpression<Internal::IsGreaterThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001783 }
1784
1785 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001786 BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001787 operator <= ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001788 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001789 }
1790
1791 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001792 BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001793 operator >= ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001794 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001795 }
1796
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001797 BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001798 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001799 }
1800
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001801 BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001802 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001803 }
1804
Phil Nashab036682014-06-02 07:48:03 +01001805 void endExpression() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001806 m_truthy = m_lhs ? true : false;
Phil Nashab036682014-06-02 07:48:03 +01001807 m_rb
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001808 .setResultType( m_truthy )
1809 .endExpression( *this );
Phil Nash176eb812012-05-11 08:17:16 +01001810 }
1811
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001812 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1813 dest = Catch::toString( m_truthy );
1814 }
Phil Nash176eb812012-05-11 08:17:16 +01001815
1816private:
Phil Nash9902ac92012-10-09 20:58:33 +01001817 template<Internal::Operator Op, typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001818 BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const {
1819 return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs );
1820 }
1821
1822 template<Internal::Operator Op>
1823 BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const {
1824 return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs );
Phil Nash9902ac92012-10-09 20:58:33 +01001825 }
1826
1827private:
Phil Nashab036682014-06-02 07:48:03 +01001828 ResultBuilder& m_rb;
Phil Nash176eb812012-05-11 08:17:16 +01001829 T m_lhs;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001830 bool m_truthy;
1831};
1832
1833template<typename LhsT, Internal::Operator Op, typename RhsT>
1834class BinaryExpression : public DecomposedExpression {
1835public:
1836 BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs )
1837 : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {}
1838
Phil Nash0952b762017-02-28 14:19:09 +00001839 BinaryExpression& operator = ( BinaryExpression& );
1840
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001841 void endExpression() const {
1842 m_rb
1843 .setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
1844 .endExpression( *this );
1845 }
1846
1847 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
1848 return true;
1849 }
1850
1851 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1852 std::string lhs = Catch::toString( m_lhs );
1853 std::string rhs = Catch::toString( m_rhs );
1854 char delim = lhs.size() + rhs.size() < 40 &&
1855 lhs.find('\n') == std::string::npos &&
1856 rhs.find('\n') == std::string::npos ? ' ' : '\n';
1857 dest.reserve( 7 + lhs.size() + rhs.size() );
1858 // 2 for spaces around operator
1859 // 2 for operator
1860 // 2 for parentheses (conditionally added later)
1861 // 1 for negation (conditionally added later)
1862 dest = lhs;
1863 dest += delim;
1864 dest += Internal::OperatorTraits<Op>::getName();
1865 dest += delim;
1866 dest += rhs;
1867 }
1868
1869private:
1870 ResultBuilder& m_rb;
1871 LhsT m_lhs;
1872 RhsT m_rhs;
1873};
1874
1875template<typename ArgT, typename MatcherT>
1876class MatchExpression : public DecomposedExpression {
1877public:
1878 MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString )
1879 : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {}
1880
1881 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
1882 return true;
1883 }
1884
1885 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1886 std::string matcherAsString = m_matcher.toString();
1887 dest = Catch::toString( m_arg );
1888 dest += ' ';
1889 if( matcherAsString == Detail::unprintableString )
1890 dest += m_matcherString;
1891 else
1892 dest += matcherAsString;
1893 }
1894
1895private:
1896 ArgT m_arg;
1897 MatcherT m_matcher;
1898 char const* m_matcherString;
Phil Nash176eb812012-05-11 08:17:16 +01001899};
1900
Phil Nash176eb812012-05-11 08:17:16 +01001901} // end namespace Catch
1902
Phil Nashab036682014-06-02 07:48:03 +01001903
Phil Nash89d2a3f2012-05-16 15:09:17 +01001904namespace Catch {
1905
Phil Nash89d2a3f2012-05-16 15:09:17 +01001906 template<typename T>
Phil Nash21f7ef62015-06-29 18:05:23 +01001907 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
Phil Nashab036682014-06-02 07:48:03 +01001908 return ExpressionLhs<T const&>( *this, operand );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001909 }
1910
Phil Nash21f7ef62015-06-29 18:05:23 +01001911 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
Phil Nashab036682014-06-02 07:48:03 +01001912 return ExpressionLhs<bool>( *this, value );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001913 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001914
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001915 template<typename ArgT, typename MatcherT>
1916 inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
1917 char const* matcherString ) {
1918 MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString );
1919 setResultType( matcher.match( arg ) );
1920 endExpression( expr );
1921 }
1922
Phil Nashab036682014-06-02 07:48:03 +01001923} // namespace Catch
Phil Nash89d2a3f2012-05-16 15:09:17 +01001924
Phil Nasha2773812013-02-02 20:37:58 +00001925// #included from: catch_message.h
1926#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1927
1928#include <string>
1929
1930namespace Catch {
1931
1932 struct MessageInfo {
1933 MessageInfo( std::string const& _macroName,
1934 SourceLineInfo const& _lineInfo,
1935 ResultWas::OfType _type );
1936
1937 std::string macroName;
1938 SourceLineInfo lineInfo;
1939 ResultWas::OfType type;
1940 std::string message;
1941 unsigned int sequence;
1942
1943 bool operator == ( MessageInfo const& other ) const {
1944 return sequence == other.sequence;
1945 }
1946 bool operator < ( MessageInfo const& other ) const {
1947 return sequence < other.sequence;
1948 }
1949 private:
1950 static unsigned int globalCount;
1951 };
1952
Phil Nashb5fd5a62013-06-28 17:09:57 +01001953 struct MessageBuilder {
1954 MessageBuilder( std::string const& macroName,
1955 SourceLineInfo const& lineInfo,
1956 ResultWas::OfType type )
1957 : m_info( macroName, lineInfo, type )
1958 {}
Phil Nasha2773812013-02-02 20:37:58 +00001959
1960 template<typename T>
Phil Nashb5fd5a62013-06-28 17:09:57 +01001961 MessageBuilder& operator << ( T const& value ) {
1962 m_stream << value;
Phil Nasha2773812013-02-02 20:37:58 +00001963 return *this;
1964 }
Phil Nashb5fd5a62013-06-28 17:09:57 +01001965
1966 MessageInfo m_info;
1967 std::ostringstream m_stream;
Phil Nasha2773812013-02-02 20:37:58 +00001968 };
1969
Phil Nashb5fd5a62013-06-28 17:09:57 +01001970 class ScopedMessage {
Phil Nasha2773812013-02-02 20:37:58 +00001971 public:
Phil Nashb5fd5a62013-06-28 17:09:57 +01001972 ScopedMessage( MessageBuilder const& builder );
Phil Nash9241e432014-05-20 18:50:59 +01001973 ScopedMessage( ScopedMessage const& other );
Phil Nashb5fd5a62013-06-28 17:09:57 +01001974 ~ScopedMessage();
1975
1976 MessageInfo m_info;
Phil Nasha2773812013-02-02 20:37:58 +00001977 };
1978
1979} // end namespace Catch
1980
Phil Nashd31737f2012-05-09 19:04:00 +01001981// #included from: catch_interfaces_capture.h
Phil Nash3b80af72012-08-09 07:47:30 +01001982#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001983
Phil Nashd31737f2012-05-09 19:04:00 +01001984#include <string>
1985
Phil Nash89d2a3f2012-05-16 15:09:17 +01001986namespace Catch {
1987
Phil Nasha1fbfea2012-12-01 23:57:18 +00001988 class TestCase;
Phil Nashce612bf2012-11-01 08:27:09 +00001989 class AssertionResult;
1990 struct AssertionInfo;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001991 struct SectionInfo;
Phil Nash0c1c9fa2015-09-27 03:28:14 -07001992 struct SectionEndInfo;
Phil Nashb5fd5a62013-06-28 17:09:57 +01001993 struct MessageInfo;
Phil Nasha2773812013-02-02 20:37:58 +00001994 class ScopedMessageBuilder;
Phil Nash3649fdf2013-12-03 18:53:55 +00001995 struct Counts;
Phil Nashd31737f2012-05-09 19:04:00 +01001996
Phil Nash89d2a3f2012-05-16 15:09:17 +01001997 struct IResultCapture {
Phil Nashd31737f2012-05-09 19:04:00 +01001998
Phil Nasha695eb92012-08-13 07:46:10 +01001999 virtual ~IResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01002000
Phil Nasha2773812013-02-02 20:37:58 +00002001 virtual void assertionEnded( AssertionResult const& result ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002002 virtual bool sectionStarted( SectionInfo const& sectionInfo,
Phil Nash89d2a3f2012-05-16 15:09:17 +01002003 Counts& assertions ) = 0;
Phil Nash0c1c9fa2015-09-27 03:28:14 -07002004 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
2005 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
Phil Nashb5fd5a62013-06-28 17:09:57 +01002006 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
2007 virtual void popScopedMessage( MessageInfo const& message ) = 0;
Phil Nasha2773812013-02-02 20:37:58 +00002008
Phil Nash89d2a3f2012-05-16 15:09:17 +01002009 virtual std::string getCurrentTestName() const = 0;
Phil Nashce612bf2012-11-01 08:27:09 +00002010 virtual const AssertionResult* getLastResult() const = 0;
Phil Nash93b61e12014-08-22 19:35:41 +01002011
2012 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01002013 };
Phil Nashab036682014-06-02 07:48:03 +01002014
2015 IResultCapture& getResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01002016}
2017
Phil Nash3649fdf2013-12-03 18:53:55 +00002018// #included from: catch_debugger.h
2019#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01002020
Phil Nash04a33642013-08-16 19:09:09 +01002021// #included from: catch_platform.h
2022#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
2023
Phil Nashd31737f2012-05-09 19:04:00 +01002024#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002025# define CATCH_PLATFORM_MAC
Phil Nashd31737f2012-05-09 19:04:00 +01002026#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002027# define CATCH_PLATFORM_IPHONE
2028#elif defined(linux) || defined(__linux) || defined(__linux__)
2029# define CATCH_PLATFORM_LINUX
Phil Nash04a33642013-08-16 19:09:09 +01002030#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002031# define CATCH_PLATFORM_WINDOWS
2032# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
2033# define CATCH_DEFINES_NOMINMAX
2034# endif
2035# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
2036# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN
2037# endif
Phil Nashd31737f2012-05-09 19:04:00 +01002038#endif
2039
Phil Nash3649fdf2013-12-03 18:53:55 +00002040#include <string>
2041
2042namespace Catch{
2043
2044 bool isDebuggerActive();
2045 void writeToDebugConsole( std::string const& text );
2046}
2047
Phil Nashd31737f2012-05-09 19:04:00 +01002048#ifdef CATCH_PLATFORM_MAC
2049
Phil Nash3649fdf2013-12-03 18:53:55 +00002050 // The following code snippet based on:
Phil Nashd31737f2012-05-09 19:04:00 +01002051 // http://cocoawithlove.com/2008/03/break-into-debugger.html
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002052 #if defined(__ppc64__) || defined(__ppc__)
2053 #define CATCH_TRAP() \
2054 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
2055 : : : "memory","r0","r3","r4" )
2056 #else
2057 #define CATCH_TRAP() __asm__("int $3\n" : : )
Phil Nashd31737f2012-05-09 19:04:00 +01002058 #endif
2059
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002060#elif defined(CATCH_PLATFORM_LINUX)
2061 // If we can use inline assembler, do it because this allows us to break
2062 // directly at the location of the failing check instead of breaking inside
2063 // raise() called from it, i.e. one stack frame below.
2064 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
2065 #define CATCH_TRAP() asm volatile ("int $3")
2066 #else // Fall back to the generic way.
2067 #include <signal.h>
2068
2069 #define CATCH_TRAP() raise(SIGTRAP)
2070 #endif
Phil Nashd31737f2012-05-09 19:04:00 +01002071#elif defined(_MSC_VER)
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002072 #define CATCH_TRAP() __debugbreak()
Phil Nash176eb812012-05-11 08:17:16 +01002073#elif defined(__MINGW32__)
Phil Nash176eb812012-05-11 08:17:16 +01002074 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002075 #define CATCH_TRAP() DebugBreak()
Phil Nashd31737f2012-05-09 19:04:00 +01002076#endif
2077
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002078#ifdef CATCH_TRAP
2079 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
2080#else
2081 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
Phil Nash3649fdf2013-12-03 18:53:55 +00002082#endif
Phil Nashd31737f2012-05-09 19:04:00 +01002083
Phil Nashab036682014-06-02 07:48:03 +01002084// #included from: catch_interfaces_runner.h
2085#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
Phil Nash37186a12013-03-13 12:19:30 +00002086
Phil Nasha70fbe32012-08-31 08:10:36 +01002087namespace Catch {
Phil Nash3649fdf2013-12-03 18:53:55 +00002088 class TestCase;
Phil Nasha70fbe32012-08-31 08:10:36 +01002089
Phil Nashab036682014-06-02 07:48:03 +01002090 struct IRunner {
2091 virtual ~IRunner();
2092 virtual bool aborting() const = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01002093 };
2094}
2095
Phil Nashd08cee22017-02-13 16:15:42 +00002096// #included from: catch_type_traits.hpp
2097#define TWOBLUECUBES_CATCH_TYPE_TRAITS_HPP_INCLUDED
2098
2099#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2100#include <type_traits>
2101#endif
2102
2103namespace Catch {
2104
2105#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2106
2107 template <typename T>
2108 using add_lvalue_reference = std::add_lvalue_reference<T>;
2109
2110 template <typename T>
2111 using add_const = std::add_const<T>;
2112
2113#else
2114
2115 template <typename T>
2116 struct add_const {
2117 typedef const T type;
2118 };
2119
2120 template <typename T>
2121 struct add_lvalue_reference {
2122 typedef T& type;
2123 };
2124 template <typename T>
2125 struct add_lvalue_reference<T&> {
2126 typedef T& type;
2127 };
2128 // No && overload, because that is C++11, in which case we have
2129 // proper type_traits implementation from the standard library
2130
2131#endif
2132
2133}
2134
Phil Nash0952b762017-02-28 14:19:09 +00002135#if defined(CATCH_CONFIG_FAST_COMPILE)
2136///////////////////////////////////////////////////////////////////////////////
2137// We can speedup compilation significantly by breaking into debugger lower in
2138// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER
2139// macro in each assertion
2140#define INTERNAL_CATCH_REACT( resultBuilder ) \
2141 resultBuilder.react();
2142#else
Phil Nashce612bf2012-11-01 08:27:09 +00002143///////////////////////////////////////////////////////////////////////////////
Phil Nashab036682014-06-02 07:48:03 +01002144// In the event of a failure works out if the debugger needs to be invoked
2145// and/or an exception thrown and takes appropriate action.
2146// This needs to be done as a macro so the debugger will stop in the user
2147// source code rather than in Catch library code
2148#define INTERNAL_CATCH_REACT( resultBuilder ) \
2149 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2150 resultBuilder.react();
Phil Nash0952b762017-02-28 14:19:09 +00002151#endif
Phil Nashce612bf2012-11-01 08:27:09 +00002152
2153///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002154#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002155 do { \
Phil Nashab036682014-06-02 07:48:03 +01002156 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002157 try { \
Phil Nashae5ee2c2016-02-29 08:17:18 +00002158 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
Phil Nash21f7ef62015-06-29 18:05:23 +01002159 ( __catchResult <= expr ).endExpression(); \
Phil Nash0952b762017-02-28 14:19:09 +00002160 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
Phil Nashce612bf2012-11-01 08:27:09 +00002161 } \
Phil Nashab036682014-06-02 07:48:03 +01002162 catch( ... ) { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002163 __catchResult.useActiveException( resultDisposition ); \
Phil Nashab036682014-06-02 07:48:03 +01002164 } \
2165 INTERNAL_CATCH_REACT( __catchResult ) \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002166 } 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
2167 // 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 +00002168
2169///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002170#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
2171 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2172 if( Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00002173
2174///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002175#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
2176 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2177 if( !Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00002178
2179///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002180#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002181 do { \
Phil Nashab036682014-06-02 07:48:03 +01002182 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002183 try { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002184 static_cast<void>(expr); \
Phil Nashab036682014-06-02 07:48:03 +01002185 __catchResult.captureResult( Catch::ResultWas::Ok ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002186 } \
2187 catch( ... ) { \
Phil Nashab036682014-06-02 07:48:03 +01002188 __catchResult.useActiveException( resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002189 } \
Phil Nashab036682014-06-02 07:48:03 +01002190 INTERNAL_CATCH_REACT( __catchResult ) \
2191 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002192
2193///////////////////////////////////////////////////////////////////////////////
Phil Nash5bbdc8f2015-07-15 23:03:11 +01002194#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002195 do { \
Phil Nash5bbdc8f2015-07-15 23:03:11 +01002196 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002197 if( __catchResult.allowThrows() ) \
2198 try { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002199 static_cast<void>(expr); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002200 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2201 } \
2202 catch( ... ) { \
Phil Nash5bbdc8f2015-07-15 23:03:11 +01002203 __catchResult.captureExpectedException( matcher ); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002204 } \
2205 else \
Phil Nashab036682014-06-02 07:48:03 +01002206 __catchResult.captureResult( Catch::ResultWas::Ok ); \
Phil Nashab036682014-06-02 07:48:03 +01002207 INTERNAL_CATCH_REACT( __catchResult ) \
2208 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002209
2210///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002211#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002212 do { \
Phil Nashd08cee22017-02-13 16:15:42 +00002213 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002214 if( __catchResult.allowThrows() ) \
2215 try { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002216 static_cast<void>(expr); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002217 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2218 } \
Phil Nashd08cee22017-02-13 16:15:42 +00002219 catch( Catch::add_const<Catch::add_lvalue_reference<exceptionType>::type>::type ) { \
Phil Nashacdd3b52014-06-30 07:35:36 +01002220 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2221 } \
2222 catch( ... ) { \
2223 __catchResult.useActiveException( resultDisposition ); \
2224 } \
2225 else \
Phil Nashab036682014-06-02 07:48:03 +01002226 __catchResult.captureResult( Catch::ResultWas::Ok ); \
Phil Nashab036682014-06-02 07:48:03 +01002227 INTERNAL_CATCH_REACT( __catchResult ) \
2228 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002229
2230///////////////////////////////////////////////////////////////////////////////
Phil Nash859760a2013-12-14 14:34:05 +00002231#ifdef CATCH_CONFIG_VARIADIC_MACROS
2232 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
2233 do { \
Phil Nashab036682014-06-02 07:48:03 +01002234 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2235 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2236 __catchResult.captureResult( messageType ); \
2237 INTERNAL_CATCH_REACT( __catchResult ) \
2238 } while( Catch::alwaysFalse() )
Phil Nash859760a2013-12-14 14:34:05 +00002239#else
2240 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
2241 do { \
Phil Nashab036682014-06-02 07:48:03 +01002242 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2243 __catchResult << log + ::Catch::StreamEndStop(); \
2244 __catchResult.captureResult( messageType ); \
2245 INTERNAL_CATCH_REACT( __catchResult ) \
2246 } while( Catch::alwaysFalse() )
Phil Nash859760a2013-12-14 14:34:05 +00002247#endif
Phil Nashce612bf2012-11-01 08:27:09 +00002248
2249///////////////////////////////////////////////////////////////////////////////
Phil Nashb5fd5a62013-06-28 17:09:57 +01002250#define INTERNAL_CATCH_INFO( log, macroName ) \
2251 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
Phil Nashce612bf2012-11-01 08:27:09 +00002252
2253///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002254#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002255 do { \
Phil Nash7424b232015-12-28 15:07:32 +00002256 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002257 try { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002258 __catchResult.captureMatch( arg, matcher, #matcher ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002259 } catch( ... ) { \
Phil Nashab036682014-06-02 07:48:03 +01002260 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002261 } \
Phil Nashab036682014-06-02 07:48:03 +01002262 INTERNAL_CATCH_REACT( __catchResult ) \
2263 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002264
Phil Nash3649fdf2013-12-03 18:53:55 +00002265// #included from: internal/catch_section.h
2266#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2267
2268// #included from: catch_section_info.h
2269#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2270
Phil Nash3649fdf2013-12-03 18:53:55 +00002271// #included from: catch_totals.hpp
2272#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2273
2274#include <cstddef>
2275
2276namespace Catch {
2277
2278 struct Counts {
Phil Nash52e1e742014-07-03 08:11:38 +01002279 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
Phil Nash3649fdf2013-12-03 18:53:55 +00002280
2281 Counts operator - ( Counts const& other ) const {
2282 Counts diff;
2283 diff.passed = passed - other.passed;
2284 diff.failed = failed - other.failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002285 diff.failedButOk = failedButOk - other.failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002286 return diff;
2287 }
2288 Counts& operator += ( Counts const& other ) {
2289 passed += other.passed;
2290 failed += other.failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002291 failedButOk += other.failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002292 return *this;
2293 }
2294
2295 std::size_t total() const {
Phil Nash52e1e742014-07-03 08:11:38 +01002296 return passed + failed + failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002297 }
Phil Nash28c2e072014-07-09 19:22:49 +01002298 bool allPassed() const {
2299 return failed == 0 && failedButOk == 0;
2300 }
Phil Nashd76e0812014-12-30 18:26:07 +00002301 bool allOk() const {
2302 return failed == 0;
2303 }
Phil Nash3649fdf2013-12-03 18:53:55 +00002304
2305 std::size_t passed;
2306 std::size_t failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002307 std::size_t failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002308 };
2309
2310 struct Totals {
2311
2312 Totals operator - ( Totals const& other ) const {
2313 Totals diff;
2314 diff.assertions = assertions - other.assertions;
2315 diff.testCases = testCases - other.testCases;
2316 return diff;
2317 }
2318
2319 Totals delta( Totals const& prevTotals ) const {
2320 Totals diff = *this - prevTotals;
2321 if( diff.assertions.failed > 0 )
2322 ++diff.testCases.failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002323 else if( diff.assertions.failedButOk > 0 )
2324 ++diff.testCases.failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002325 else
2326 ++diff.testCases.passed;
2327 return diff;
2328 }
2329
2330 Totals& operator += ( Totals const& other ) {
2331 assertions += other.assertions;
2332 testCases += other.testCases;
2333 return *this;
2334 }
2335
2336 Counts assertions;
2337 Counts testCases;
2338 };
2339}
Phil Nashce612bf2012-11-01 08:27:09 +00002340
Phil Nashd08cee22017-02-13 16:15:42 +00002341#include <string>
2342
Phil Nash0c1c9fa2015-09-27 03:28:14 -07002343namespace Catch {
2344
2345 struct SectionInfo {
2346 SectionInfo
2347 ( SourceLineInfo const& _lineInfo,
2348 std::string const& _name,
2349 std::string const& _description = std::string() );
2350
2351 std::string name;
2352 std::string description;
2353 SourceLineInfo lineInfo;
2354 };
2355
2356 struct SectionEndInfo {
2357 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
2358 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
2359 {}
2360
2361 SectionInfo sectionInfo;
2362 Counts prevAssertions;
2363 double durationInSeconds;
2364 };
2365
2366} // end namespace Catch
2367
Phil Nashaa7123b2013-08-15 19:01:00 +01002368// #included from: catch_timer.h
2369#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2370
Phil Nash04a33642013-08-16 19:09:09 +01002371#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01002372typedef unsigned long long uint64_t;
2373#else
2374#include <stdint.h>
2375#endif
2376
2377namespace Catch {
2378
2379 class Timer {
2380 public:
2381 Timer() : m_ticks( 0 ) {}
2382 void start();
Phil Nash4caabfa2014-09-03 19:23:22 +01002383 unsigned int getElapsedMicroseconds() const;
Phil Nashaa7123b2013-08-15 19:01:00 +01002384 unsigned int getElapsedMilliseconds() const;
2385 double getElapsedSeconds() const;
2386
2387 private:
2388 uint64_t m_ticks;
2389 };
2390
2391} // namespace Catch
2392
Phil Nashce612bf2012-11-01 08:27:09 +00002393#include <string>
2394
2395namespace Catch {
2396
Phil Nashe54ac702014-10-21 07:25:26 +01002397 class Section : NonCopyable {
Phil Nashce612bf2012-11-01 08:27:09 +00002398 public:
Phil Nashce562092014-07-09 07:40:37 +01002399 Section( SectionInfo const& info );
Phil Nash3649fdf2013-12-03 18:53:55 +00002400 ~Section();
Phil Nashce612bf2012-11-01 08:27:09 +00002401
2402 // This indicates whether the section should be executed or not
Phil Nashce562092014-07-09 07:40:37 +01002403 operator bool() const;
Phil Nashce612bf2012-11-01 08:27:09 +00002404
2405 private:
Phil Nasha1fbfea2012-12-01 23:57:18 +00002406 SectionInfo m_info;
Phil Nashce612bf2012-11-01 08:27:09 +00002407
2408 std::string m_name;
2409 Counts m_assertions;
2410 bool m_sectionIncluded;
Phil Nashaa7123b2013-08-15 19:01:00 +01002411 Timer m_timer;
Phil Nashce612bf2012-11-01 08:27:09 +00002412 };
2413
2414} // end namespace Catch
2415
Phil Nash93906752013-03-16 20:21:51 +00002416#ifdef CATCH_CONFIG_VARIADIC_MACROS
2417 #define INTERNAL_CATCH_SECTION( ... ) \
Phil Nashce562092014-07-09 07:40:37 +01002418 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 +00002419#else
2420 #define INTERNAL_CATCH_SECTION( name, desc ) \
Phil Nashce562092014-07-09 07:40:37 +01002421 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 +00002422#endif
Phil Nashce612bf2012-11-01 08:27:09 +00002423
2424// #included from: internal/catch_generators.hpp
2425#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2426
2427#include <iterator>
2428#include <vector>
2429#include <string>
2430#include <stdlib.h>
2431
2432namespace Catch {
2433
2434template<typename T>
2435struct IGenerator {
2436 virtual ~IGenerator() {}
2437 virtual T getValue( std::size_t index ) const = 0;
2438 virtual std::size_t size () const = 0;
2439};
2440
2441template<typename T>
2442class BetweenGenerator : public IGenerator<T> {
2443public:
2444 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
2445
2446 virtual T getValue( std::size_t index ) const {
Phil Nash2e7d9662013-01-16 09:44:43 +00002447 return m_from+static_cast<int>( index );
Phil Nashce612bf2012-11-01 08:27:09 +00002448 }
2449
2450 virtual std::size_t size() const {
2451 return static_cast<std::size_t>( 1+m_to-m_from );
2452 }
2453
2454private:
2455
2456 T m_from;
2457 T m_to;
2458};
2459
2460template<typename T>
2461class ValuesGenerator : public IGenerator<T> {
2462public:
2463 ValuesGenerator(){}
2464
2465 void add( T value ) {
2466 m_values.push_back( value );
2467 }
2468
2469 virtual T getValue( std::size_t index ) const {
2470 return m_values[index];
2471 }
2472
2473 virtual std::size_t size() const {
2474 return m_values.size();
2475 }
2476
2477private:
2478 std::vector<T> m_values;
2479};
2480
2481template<typename T>
2482class CompositeGenerator {
2483public:
2484 CompositeGenerator() : m_totalSize( 0 ) {}
2485
Phil Nasha04981b2013-03-08 09:30:25 +00002486 // *** Move semantics, similar to auto_ptr ***
Phil Nashce612bf2012-11-01 08:27:09 +00002487 CompositeGenerator( CompositeGenerator& other )
2488 : m_fileInfo( other.m_fileInfo ),
2489 m_totalSize( 0 )
2490 {
Phil Nasha04981b2013-03-08 09:30:25 +00002491 move( other );
Phil Nashce612bf2012-11-01 08:27:09 +00002492 }
2493
2494 CompositeGenerator& setFileInfo( const char* fileInfo ) {
2495 m_fileInfo = fileInfo;
2496 return *this;
2497 }
2498
2499 ~CompositeGenerator() {
2500 deleteAll( m_composed );
2501 }
2502
2503 operator T () const {
2504 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
2505
2506 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2507 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2508 for( size_t index = 0; it != itEnd; ++it )
2509 {
2510 const IGenerator<T>* generator = *it;
2511 if( overallIndex >= index && overallIndex < index + generator->size() )
2512 {
2513 return generator->getValue( overallIndex-index );
2514 }
2515 index += generator->size();
2516 }
2517 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
Phil Nasha04981b2013-03-08 09:30:25 +00002518 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 +00002519 }
2520
2521 void add( const IGenerator<T>* generator ) {
2522 m_totalSize += generator->size();
2523 m_composed.push_back( generator );
2524 }
2525
2526 CompositeGenerator& then( CompositeGenerator& other ) {
2527 move( other );
2528 return *this;
2529 }
2530
2531 CompositeGenerator& then( T value ) {
2532 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2533 valuesGen->add( value );
2534 add( valuesGen );
2535 return *this;
2536 }
2537
2538private:
2539
2540 void move( CompositeGenerator& other ) {
2541 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
2542 m_totalSize += other.m_totalSize;
2543 other.m_composed.clear();
2544 }
2545
2546 std::vector<const IGenerator<T>*> m_composed;
2547 std::string m_fileInfo;
2548 size_t m_totalSize;
2549};
2550
2551namespace Generators
2552{
2553 template<typename T>
2554 CompositeGenerator<T> between( T from, T to ) {
2555 CompositeGenerator<T> generators;
2556 generators.add( new BetweenGenerator<T>( from, to ) );
2557 return generators;
2558 }
2559
2560 template<typename T>
2561 CompositeGenerator<T> values( T val1, T val2 ) {
2562 CompositeGenerator<T> generators;
2563 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2564 valuesGen->add( val1 );
2565 valuesGen->add( val2 );
2566 generators.add( valuesGen );
2567 return generators;
2568 }
2569
2570 template<typename T>
2571 CompositeGenerator<T> values( T val1, T val2, T val3 ){
2572 CompositeGenerator<T> generators;
2573 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2574 valuesGen->add( val1 );
2575 valuesGen->add( val2 );
2576 valuesGen->add( val3 );
2577 generators.add( valuesGen );
2578 return generators;
2579 }
2580
2581 template<typename T>
2582 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2583 CompositeGenerator<T> generators;
2584 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2585 valuesGen->add( val1 );
2586 valuesGen->add( val2 );
2587 valuesGen->add( val3 );
2588 valuesGen->add( val4 );
2589 generators.add( valuesGen );
2590 return generators;
2591 }
2592
2593} // end namespace Generators
2594
2595using namespace Generators;
2596
2597} // end namespace Catch
2598
2599#define INTERNAL_CATCH_LINESTR2( line ) #line
2600#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2601
2602#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2603
2604// #included from: internal/catch_interfaces_exception.h
2605#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2606
2607#include <string>
Phil Nashe4fa62a2015-11-18 08:39:54 +00002608#include <vector>
2609
Phil Nashab036682014-06-02 07:48:03 +01002610// #included from: catch_interfaces_registry_hub.h
2611#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2612
2613#include <string>
2614
2615namespace Catch {
2616
2617 class TestCase;
2618 struct ITestCaseRegistry;
2619 struct IExceptionTranslatorRegistry;
2620 struct IExceptionTranslator;
2621 struct IReporterRegistry;
2622 struct IReporterFactory;
2623
2624 struct IRegistryHub {
2625 virtual ~IRegistryHub();
2626
2627 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2628 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2629 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2630 };
2631
2632 struct IMutableRegistryHub {
2633 virtual ~IMutableRegistryHub();
Phil Nashe73583d2015-08-07 17:30:34 +01002634 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
2635 virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
Phil Nashab036682014-06-02 07:48:03 +01002636 virtual void registerTest( TestCase const& testInfo ) = 0;
2637 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2638 };
2639
2640 IRegistryHub& getRegistryHub();
2641 IMutableRegistryHub& getMutableRegistryHub();
2642 void cleanUp();
2643 std::string translateActiveException();
2644
2645}
2646
Phil Nash89d2a3f2012-05-16 15:09:17 +01002647namespace Catch {
2648
Phil Nash89d1e6c2011-05-24 08:23:02 +01002649 typedef std::string(*exceptionTranslateFunction)();
2650
Phil Nashe4fa62a2015-11-18 08:39:54 +00002651 struct IExceptionTranslator;
2652 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2653
Phil Nash89d2a3f2012-05-16 15:09:17 +01002654 struct IExceptionTranslator {
Phil Nasha695eb92012-08-13 07:46:10 +01002655 virtual ~IExceptionTranslator();
Phil Nashe4fa62a2015-11-18 08:39:54 +00002656 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002657 };
2658
Phil Nash89d2a3f2012-05-16 15:09:17 +01002659 struct IExceptionTranslatorRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +01002660 virtual ~IExceptionTranslatorRegistry();
Phil Nash89d1e6c2011-05-24 08:23:02 +01002661
Phil Nash89d2a3f2012-05-16 15:09:17 +01002662 virtual std::string translateActiveException() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002663 };
2664
Phil Nash89d2a3f2012-05-16 15:09:17 +01002665 class ExceptionTranslatorRegistrar {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002666 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002667 class ExceptionTranslator : public IExceptionTranslator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002668 public:
2669
Phil Nash89d2a3f2012-05-16 15:09:17 +01002670 ExceptionTranslator( std::string(*translateFunction)( T& ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002671 : m_translateFunction( translateFunction )
2672 {}
2673
Phil Nashe4fa62a2015-11-18 08:39:54 +00002674 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002675 try {
Phil Nashe4fa62a2015-11-18 08:39:54 +00002676 if( it == itEnd )
2677 throw;
2678 else
2679 return (*it)->translate( it+1, itEnd );
Phil Nash89d1e6c2011-05-24 08:23:02 +01002680 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01002681 catch( T& ex ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002682 return m_translateFunction( ex );
2683 }
2684 }
2685
2686 protected:
2687 std::string(*m_translateFunction)( T& );
2688 };
2689
2690 public:
2691 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002692 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
Phil Nash3b80af72012-08-09 07:47:30 +01002693 getMutableRegistryHub().registerTranslator
Phil Nash89d1e6c2011-05-24 08:23:02 +01002694 ( new ExceptionTranslator<T>( translateFunction ) );
2695 }
2696 };
2697}
2698
2699///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +00002700#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
2701 static std::string translatorName( signature ); \
2702 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
2703 static std::string translatorName( signature )
2704
2705#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 +01002706
2707// #included from: internal/catch_approx.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002708#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01002709
Phil Nash89d1e6c2011-05-24 08:23:02 +01002710#include <cmath>
2711#include <limits>
2712
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002713#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2714#include <type_traits>
2715#endif
2716
Phil Nash89d2a3f2012-05-16 15:09:17 +01002717namespace Catch {
2718namespace Detail {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002719
Phil Nash89d2a3f2012-05-16 15:09:17 +01002720 class Approx {
2721 public:
2722 explicit Approx ( double value )
2723 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
Phil Nash0952b762017-02-28 14:19:09 +00002724 m_margin( 0.0 ),
Phil Nash89d2a3f2012-05-16 15:09:17 +01002725 m_scale( 1.0 ),
2726 m_value( value )
2727 {}
Phil Nashf721a962011-06-07 14:13:57 +01002728
Phil Nash8defc712013-04-24 19:10:02 +01002729 Approx( Approx const& other )
Phil Nash89d2a3f2012-05-16 15:09:17 +01002730 : m_epsilon( other.m_epsilon ),
Phil Nash0952b762017-02-28 14:19:09 +00002731 m_margin( other.m_margin ),
Phil Nash89d2a3f2012-05-16 15:09:17 +01002732 m_scale( other.m_scale ),
2733 m_value( other.m_value )
2734 {}
Phil Nashf721a962011-06-07 14:13:57 +01002735
Phil Nash89d2a3f2012-05-16 15:09:17 +01002736 static Approx custom() {
2737 return Approx( 0 );
2738 }
Phil Nashf721a962011-06-07 14:13:57 +01002739
Phil Nash89d2a3f2012-05-16 15:09:17 +01002740 Approx operator()( double value ) {
2741 Approx approx( value );
2742 approx.epsilon( m_epsilon );
Phil Nash0952b762017-02-28 14:19:09 +00002743 approx.margin( m_margin );
Phil Nash89d2a3f2012-05-16 15:09:17 +01002744 approx.scale( m_scale );
2745 return approx;
2746 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002747
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002748#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2749 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2750 friend bool operator == ( const T& lhs, Approx const& rhs ) {
2751 // Thanks to Richard Harris for his help refining this formula
2752 auto lhs_v = double(lhs);
Phil Nash0952b762017-02-28 14:19:09 +00002753 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)));
2754 if (relativeOK) {
2755 return true;
2756 }
2757 return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002758 }
2759
2760 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2761 friend bool operator == ( Approx const& lhs, const T& rhs ) {
2762 return operator==( rhs, lhs );
2763 }
2764
2765 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2766 friend bool operator != ( T lhs, Approx const& rhs ) {
2767 return !operator==( lhs, rhs );
2768 }
2769
2770 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2771 friend bool operator != ( Approx const& lhs, T rhs ) {
2772 return !operator==( rhs, lhs );
2773 }
2774
2775 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2776 friend bool operator <= ( T lhs, Approx const& rhs )
2777 {
2778 return double(lhs) < rhs.m_value || lhs == rhs;
2779 }
2780
2781 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2782 friend bool operator <= ( Approx const& lhs, T rhs )
2783 {
2784 return lhs.m_value < double(rhs) || lhs == rhs;
2785 }
2786
2787 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2788 friend bool operator >= ( T lhs, Approx const& rhs )
2789 {
2790 return double(lhs) > rhs.m_value || lhs == rhs;
2791 }
2792
2793 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2794 friend bool operator >= ( Approx const& lhs, T rhs )
2795 {
2796 return lhs.m_value > double(rhs) || lhs == rhs;
2797 }
2798#else
Phil Nash8defc712013-04-24 19:10:02 +01002799 friend bool operator == ( double lhs, Approx const& rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002800 // Thanks to Richard Harris for his help refining this formula
Phil Nash0952b762017-02-28 14:19:09 +00002801 bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) );
2802 if (relativeOK) {
2803 return true;
2804 }
2805 return std::fabs(lhs - rhs.m_value) < rhs.m_margin;
Phil Nash89d2a3f2012-05-16 15:09:17 +01002806 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002807
Phil Nash8defc712013-04-24 19:10:02 +01002808 friend bool operator == ( Approx const& lhs, double rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002809 return operator==( rhs, lhs );
2810 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002811
Phil Nash8defc712013-04-24 19:10:02 +01002812 friend bool operator != ( double lhs, Approx const& rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002813 return !operator==( lhs, rhs );
2814 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002815
Phil Nash8defc712013-04-24 19:10:02 +01002816 friend bool operator != ( Approx const& lhs, double rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002817 return !operator==( rhs, lhs );
2818 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002819
Phil Nash3b2f2062017-01-11 16:43:56 +00002820 friend bool operator <= ( double lhs, Approx const& rhs )
2821 {
2822 return lhs < rhs.m_value || lhs == rhs;
2823 }
2824
2825 friend bool operator <= ( Approx const& lhs, double rhs )
2826 {
2827 return lhs.m_value < rhs || lhs == rhs;
2828 }
2829
2830 friend bool operator >= ( double lhs, Approx const& rhs )
2831 {
2832 return lhs > rhs.m_value || lhs == rhs;
2833 }
2834
2835 friend bool operator >= ( Approx const& lhs, double rhs )
2836 {
2837 return lhs.m_value > rhs || lhs == rhs;
2838 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002839#endif
Phil Nash3b2f2062017-01-11 16:43:56 +00002840
Phil Nash89d2a3f2012-05-16 15:09:17 +01002841 Approx& epsilon( double newEpsilon ) {
2842 m_epsilon = newEpsilon;
2843 return *this;
2844 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002845
Phil Nash0952b762017-02-28 14:19:09 +00002846 Approx& margin( double newMargin ) {
2847 m_margin = newMargin;
2848 return *this;
2849 }
2850
Phil Nash89d2a3f2012-05-16 15:09:17 +01002851 Approx& scale( double newScale ) {
2852 m_scale = newScale;
2853 return *this;
2854 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002855
Phil Nash89d2a3f2012-05-16 15:09:17 +01002856 std::string toString() const {
2857 std::ostringstream oss;
Phil Nashf385a0b2013-12-19 18:42:25 +00002858 oss << "Approx( " << Catch::toString( m_value ) << " )";
Phil Nash89d2a3f2012-05-16 15:09:17 +01002859 return oss.str();
2860 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002861
Phil Nash89d2a3f2012-05-16 15:09:17 +01002862 private:
2863 double m_epsilon;
Phil Nash0952b762017-02-28 14:19:09 +00002864 double m_margin;
Phil Nash89d2a3f2012-05-16 15:09:17 +01002865 double m_scale;
2866 double m_value;
2867 };
2868}
2869
2870template<>
Phil Nash8defc712013-04-24 19:10:02 +01002871inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002872 return value.toString();
2873}
Phil Nash89d1e6c2011-05-24 08:23:02 +01002874
2875} // end namespace Catch
2876
Phil Nash0952b762017-02-28 14:19:09 +00002877// #included from: internal/catch_matchers_string.h
2878#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
2879
2880namespace Catch {
2881namespace Matchers {
2882
2883 namespace StdString {
2884
2885 struct CasedString
2886 {
2887 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
2888 std::string adjustString( std::string const& str ) const;
2889 std::string caseSensitivitySuffix() const;
2890
2891 CaseSensitive::Choice m_caseSensitivity;
2892 std::string m_str;
2893 };
2894
2895 struct StringMatcherBase : MatcherBase<std::string> {
2896 StringMatcherBase( std::string operation, CasedString const& comparator );
2897 virtual std::string describe() const CATCH_OVERRIDE;
2898
2899 CasedString m_comparator;
2900 std::string m_operation;
2901 };
2902
2903 struct EqualsMatcher : StringMatcherBase {
2904 EqualsMatcher( CasedString const& comparator );
2905 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2906 };
2907 struct ContainsMatcher : StringMatcherBase {
2908 ContainsMatcher( CasedString const& comparator );
2909 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2910 };
2911 struct StartsWithMatcher : StringMatcherBase {
2912 StartsWithMatcher( CasedString const& comparator );
2913 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2914 };
2915 struct EndsWithMatcher : StringMatcherBase {
2916 EndsWithMatcher( CasedString const& comparator );
2917 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2918 };
2919
2920 } // namespace StdString
2921
2922 // The following functions create the actual matcher objects.
2923 // This allows the types to be inferred
2924
2925 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2926 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2927 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2928 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2929
2930} // namespace Matchers
2931} // namespace Catch
2932
2933// #included from: internal/catch_matchers_vector.h
2934#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
2935
2936namespace Catch {
2937namespace Matchers {
2938
2939 namespace Vector {
2940
2941 template<typename T>
2942 struct ContainsElementMatcher : MatcherBase<std::vector<T>, T> {
2943
2944 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
2945
2946 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
2947 return std::find(v.begin(), v.end(), m_comparator) != v.end();
2948 }
2949
2950 virtual std::string describe() const CATCH_OVERRIDE {
2951 return "Contains: " + Catch::toString( m_comparator );
2952 }
2953
2954 T const& m_comparator;
2955 };
2956
2957 template<typename T>
2958 struct ContainsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
2959
2960 ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
2961
2962 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
2963 // !TBD: see note in EqualsMatcher
2964 if (m_comparator.size() > v.size())
2965 return false;
2966 for (size_t i = 0; i < m_comparator.size(); ++i)
2967 if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end())
2968 return false;
2969 return true;
2970 }
2971 virtual std::string describe() const CATCH_OVERRIDE {
2972 return "Contains: " + Catch::toString( m_comparator );
2973 }
2974
2975 std::vector<T> const& m_comparator;
2976 };
2977
2978 template<typename T>
2979 struct EqualsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
2980
2981 EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
2982
2983 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
2984 // !TBD: This currently works if all elements can be compared using !=
2985 // - a more general approach would be via a compare template that defaults
2986 // to using !=. but could be specialised for, e.g. std::vector<T> etc
2987 // - then just call that directly
2988 if (m_comparator.size() != v.size())
2989 return false;
2990 for (size_t i = 0; i < v.size(); ++i)
2991 if (m_comparator[i] != v[i])
2992 return false;
2993 return true;
2994 }
2995 virtual std::string describe() const CATCH_OVERRIDE {
2996 return "Equals: " + Catch::toString( m_comparator );
2997 }
2998 std::vector<T> const& m_comparator;
2999 };
3000
3001 } // namespace Vector
3002
3003 // The following functions create the actual matcher objects.
3004 // This allows the types to be inferred
3005
3006 template<typename T>
3007 Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
3008 return Vector::ContainsMatcher<T>( comparator );
3009 }
3010
3011 template<typename T>
3012 Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
3013 return Vector::ContainsElementMatcher<T>( comparator );
3014 }
3015
3016 template<typename T>
3017 Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
3018 return Vector::EqualsMatcher<T>( comparator );
3019 }
3020
3021} // namespace Matchers
3022} // namespace Catch
3023
Phil Nashacdd3b52014-06-30 07:35:36 +01003024// #included from: internal/catch_interfaces_tag_alias_registry.h
3025#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
3026
3027// #included from: catch_tag_alias.h
3028#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
3029
3030#include <string>
3031
3032namespace Catch {
3033
3034 struct TagAlias {
3035 TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
3036
3037 std::string tag;
3038 SourceLineInfo lineInfo;
3039 };
3040
3041 struct RegistrarForTagAliases {
3042 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
3043 };
3044
3045} // end namespace Catch
3046
3047#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
3048// #included from: catch_option.hpp
3049#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
3050
3051namespace Catch {
3052
3053 // An optional type
3054 template<typename T>
3055 class Option {
3056 public:
Phil Nashb971fe72015-07-02 08:21:38 +01003057 Option() : nullableValue( CATCH_NULL ) {}
Phil Nashacdd3b52014-06-30 07:35:36 +01003058 Option( T const& _value )
3059 : nullableValue( new( storage ) T( _value ) )
3060 {}
3061 Option( Option const& _other )
Phil Nashb971fe72015-07-02 08:21:38 +01003062 : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
Phil Nashacdd3b52014-06-30 07:35:36 +01003063 {}
3064
3065 ~Option() {
3066 reset();
3067 }
3068
3069 Option& operator= ( Option const& _other ) {
3070 if( &_other != this ) {
3071 reset();
3072 if( _other )
3073 nullableValue = new( storage ) T( *_other );
3074 }
3075 return *this;
3076 }
3077 Option& operator = ( T const& _value ) {
3078 reset();
3079 nullableValue = new( storage ) T( _value );
3080 return *this;
3081 }
3082
3083 void reset() {
3084 if( nullableValue )
3085 nullableValue->~T();
Phil Nashb971fe72015-07-02 08:21:38 +01003086 nullableValue = CATCH_NULL;
Phil Nashacdd3b52014-06-30 07:35:36 +01003087 }
3088
3089 T& operator*() { return *nullableValue; }
3090 T const& operator*() const { return *nullableValue; }
3091 T* operator->() { return nullableValue; }
3092 const T* operator->() const { return nullableValue; }
3093
3094 T valueOr( T const& defaultValue ) const {
3095 return nullableValue ? *nullableValue : defaultValue;
3096 }
3097
Phil Nashb971fe72015-07-02 08:21:38 +01003098 bool some() const { return nullableValue != CATCH_NULL; }
3099 bool none() const { return nullableValue == CATCH_NULL; }
Phil Nashacdd3b52014-06-30 07:35:36 +01003100
Phil Nashb971fe72015-07-02 08:21:38 +01003101 bool operator !() const { return nullableValue == CATCH_NULL; }
Phil Nashacdd3b52014-06-30 07:35:36 +01003102 operator SafeBool::type() const {
3103 return SafeBool::makeSafe( some() );
3104 }
3105
3106 private:
3107 T* nullableValue;
3108 char storage[sizeof(T)];
3109 };
3110
3111} // end namespace Catch
3112
3113namespace Catch {
3114
3115 struct ITagAliasRegistry {
3116 virtual ~ITagAliasRegistry();
3117 virtual Option<TagAlias> find( std::string const& alias ) const = 0;
3118 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
3119
3120 static ITagAliasRegistry const& get();
3121 };
3122
3123} // end namespace Catch
3124
Phil Nash0f9c5512012-06-02 23:12:42 +01003125// These files are included here so the single_include script doesn't put them
3126// in the conditionally compiled sections
Phil Nash3649fdf2013-12-03 18:53:55 +00003127// #included from: internal/catch_test_case_info.h
3128#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01003129
3130#include <string>
Phil Nash3649fdf2013-12-03 18:53:55 +00003131#include <set>
3132
3133#ifdef __clang__
3134#pragma clang diagnostic push
3135#pragma clang diagnostic ignored "-Wpadded"
3136#endif
3137
3138namespace Catch {
3139
3140 struct ITestCase;
3141
3142 struct TestCaseInfo {
Phil Nash52e1e742014-07-03 08:11:38 +01003143 enum SpecialProperties{
3144 None = 0,
3145 IsHidden = 1 << 1,
3146 ShouldFail = 1 << 2,
3147 MayFail = 1 << 3,
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003148 Throws = 1 << 4,
3149 NonPortable = 1 << 5
Phil Nash52e1e742014-07-03 08:11:38 +01003150 };
3151
Phil Nash3649fdf2013-12-03 18:53:55 +00003152 TestCaseInfo( std::string const& _name,
3153 std::string const& _className,
3154 std::string const& _description,
3155 std::set<std::string> const& _tags,
Phil Nash3649fdf2013-12-03 18:53:55 +00003156 SourceLineInfo const& _lineInfo );
3157
3158 TestCaseInfo( TestCaseInfo const& other );
3159
Phil Nashb971fe72015-07-02 08:21:38 +01003160 friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
3161
Phil Nash52e1e742014-07-03 08:11:38 +01003162 bool isHidden() const;
3163 bool throws() const;
3164 bool okToFail() const;
3165 bool expectedToFail() const;
3166
Phil Nash3649fdf2013-12-03 18:53:55 +00003167 std::string name;
3168 std::string className;
3169 std::string description;
3170 std::set<std::string> tags;
Phil Nash9241e432014-05-20 18:50:59 +01003171 std::set<std::string> lcaseTags;
Phil Nash3649fdf2013-12-03 18:53:55 +00003172 std::string tagsAsString;
3173 SourceLineInfo lineInfo;
Phil Nash52e1e742014-07-03 08:11:38 +01003174 SpecialProperties properties;
Phil Nash3649fdf2013-12-03 18:53:55 +00003175 };
3176
Phil Nash65cc14c2014-05-16 18:54:48 +01003177 class TestCase : public TestCaseInfo {
Phil Nash3649fdf2013-12-03 18:53:55 +00003178 public:
3179
3180 TestCase( ITestCase* testCase, TestCaseInfo const& info );
3181 TestCase( TestCase const& other );
3182
3183 TestCase withName( std::string const& _newName ) const;
3184
3185 void invoke() const;
3186
3187 TestCaseInfo const& getTestCaseInfo() const;
3188
Phil Nash3649fdf2013-12-03 18:53:55 +00003189 void swap( TestCase& other );
3190 bool operator == ( TestCase const& other ) const;
3191 bool operator < ( TestCase const& other ) const;
3192 TestCase& operator = ( TestCase const& other );
3193
3194 private:
3195 Ptr<ITestCase> test;
3196 };
3197
3198 TestCase makeTestCase( ITestCase* testCase,
3199 std::string const& className,
3200 std::string const& name,
3201 std::string const& description,
3202 SourceLineInfo const& lineInfo );
3203}
3204
3205#ifdef __clang__
3206#pragma clang diagnostic pop
3207#endif
3208
Phil Nash0f9c5512012-06-02 23:12:42 +01003209
Phil Nash371db8b2012-05-21 18:52:09 +01003210#ifdef __OBJC__
3211// #included from: internal/catch_objc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003212#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01003213
Phil Nash371db8b2012-05-21 18:52:09 +01003214#import <objc/runtime.h>
3215
3216#include <string>
3217
3218// NB. Any general catch headers included here must be included
3219// in catch.hpp first to make sure they are included by the single
3220// header for non obj-usage
Phil Nash81528252011-08-15 09:06:31 +01003221
Phil Nash83224e62011-08-12 18:53:28 +01003222///////////////////////////////////////////////////////////////////////////////
3223// This protocol is really only here for (self) documenting purposes, since
3224// all its methods are optional.
3225@protocol OcFixture
3226
3227@optional
3228
3229-(void) setUp;
3230-(void) tearDown;
3231
3232@end
3233
Phil Nash89d2a3f2012-05-16 15:09:17 +01003234namespace Catch {
Phil Nash83224e62011-08-12 18:53:28 +01003235
Phil Nash5bc030d2012-08-16 18:48:50 +01003236 class OcMethod : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +01003237
3238 public:
3239 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
3240
3241 virtual void invoke() const {
Phil Nash53c990a2012-03-17 18:20:06 +00003242 id obj = [[m_cls alloc] init];
Phil Nash83224e62011-08-12 18:53:28 +01003243
Phil Nash53c990a2012-03-17 18:20:06 +00003244 performOptionalSelector( obj, @selector(setUp) );
3245 performOptionalSelector( obj, m_sel );
3246 performOptionalSelector( obj, @selector(tearDown) );
Phil Nash83224e62011-08-12 18:53:28 +01003247
Phil Nash53c990a2012-03-17 18:20:06 +00003248 arcSafeRelease( obj );
Phil Nash83224e62011-08-12 18:53:28 +01003249 }
Phil Nash83224e62011-08-12 18:53:28 +01003250 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01003251 virtual ~OcMethod() {}
3252
Phil Nash83224e62011-08-12 18:53:28 +01003253 Class m_cls;
3254 SEL m_sel;
3255 };
3256
Phil Nash89d2a3f2012-05-16 15:09:17 +01003257 namespace Detail{
Phil Nash83224e62011-08-12 18:53:28 +01003258
Phil Nash89d2a3f2012-05-16 15:09:17 +01003259 inline std::string getAnnotation( Class cls,
Phil Nash8defc712013-04-24 19:10:02 +01003260 std::string const& annotationName,
3261 std::string const& testCaseName ) {
Phil Nash83224e62011-08-12 18:53:28 +01003262 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
3263 SEL sel = NSSelectorFromString( selStr );
Phil Nash53c990a2012-03-17 18:20:06 +00003264 arcSafeRelease( selStr );
3265 id value = performOptionalSelector( cls, sel );
3266 if( value )
3267 return [(NSString*)value UTF8String];
Phil Nash83224e62011-08-12 18:53:28 +01003268 return "";
3269 }
3270 }
3271
Phil Nash89d2a3f2012-05-16 15:09:17 +01003272 inline size_t registerTestMethods() {
Phil Nash83224e62011-08-12 18:53:28 +01003273 size_t noTestMethods = 0;
Phil Nashb971fe72015-07-02 08:21:38 +01003274 int noClasses = objc_getClassList( CATCH_NULL, 0 );
Phil Nash83224e62011-08-12 18:53:28 +01003275
Phil Nash861a1e72012-04-28 12:29:52 +01003276 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
Phil Nash53c990a2012-03-17 18:20:06 +00003277 objc_getClassList( classes, noClasses );
Phil Nash83224e62011-08-12 18:53:28 +01003278
Phil Nash89d2a3f2012-05-16 15:09:17 +01003279 for( int c = 0; c < noClasses; c++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01003280 Class cls = classes[c];
3281 {
3282 u_int count;
3283 Method* methods = class_copyMethodList( cls, &count );
Phil Nash7004f4a2012-05-22 08:56:59 +01003284 for( u_int m = 0; m < count ; m++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01003285 SEL selector = method_getName(methods[m]);
3286 std::string methodName = sel_getName(selector);
Phil Nash3649fdf2013-12-03 18:53:55 +00003287 if( startsWith( methodName, "Catch_TestCase_" ) ) {
Phil Nash83224e62011-08-12 18:53:28 +01003288 std::string testCaseName = methodName.substr( 15 );
Phil Nash53c990a2012-03-17 18:20:06 +00003289 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
3290 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
Phil Nasha8c65432013-02-19 08:46:09 +00003291 const char* className = class_getName( cls );
Phil Nash83224e62011-08-12 18:53:28 +01003292
Phil Nash5bdae842013-02-19 19:47:18 +00003293 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
Phil Nash83224e62011-08-12 18:53:28 +01003294 noTestMethods++;
Phil Nash83224e62011-08-12 18:53:28 +01003295 }
3296 }
3297 free(methods);
3298 }
3299 }
3300 return noTestMethods;
3301 }
Phil Nash78d95a02012-03-04 21:22:36 +00003302
Phil Nash89d2a3f2012-05-16 15:09:17 +01003303 namespace Matchers {
3304 namespace Impl {
3305 namespace NSStringMatchers {
3306
Phil Nasha8c65432013-02-19 08:46:09 +00003307 template<typename MatcherT>
3308 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
Phil Nash78d95a02012-03-04 21:22:36 +00003309 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
Phil Nasha8c65432013-02-19 08:46:09 +00003310 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
Phil Nash89d2a3f2012-05-16 15:09:17 +01003311 StringHolder() {
Phil Nash53c990a2012-03-17 18:20:06 +00003312 arcSafeRelease( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003313 }
3314
3315 NSString* m_substr;
3316 };
3317
Phil Nasha8c65432013-02-19 08:46:09 +00003318 struct Equals : StringHolder<Equals> {
Phil Nash8d18d162012-03-14 20:06:14 +00003319 Equals( NSString* substr ) : StringHolder( substr ){}
3320
Phil Nasha8c65432013-02-19 08:46:09 +00003321 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003322 return (str != nil || m_substr == nil ) &&
3323 [str isEqualToString:m_substr];
Phil Nash8d18d162012-03-14 20:06:14 +00003324 }
3325
Phil Nasha8c65432013-02-19 08:46:09 +00003326 virtual std::string toString() const {
Phil Nashacdd3b52014-06-30 07:35:36 +01003327 return "equals string: " + Catch::toString( m_substr );
Phil Nash8d18d162012-03-14 20:06:14 +00003328 }
3329 };
3330
Phil Nasha8c65432013-02-19 08:46:09 +00003331 struct Contains : StringHolder<Contains> {
Phil Nash78d95a02012-03-04 21:22:36 +00003332 Contains( NSString* substr ) : StringHolder( substr ){}
3333
Phil Nasha8c65432013-02-19 08:46:09 +00003334 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003335 return (str != nil || m_substr == nil ) &&
3336 [str rangeOfString:m_substr].location != NSNotFound;
Phil Nash78d95a02012-03-04 21:22:36 +00003337 }
3338
Phil Nasha8c65432013-02-19 08:46:09 +00003339 virtual std::string toString() const {
Phil Nashacdd3b52014-06-30 07:35:36 +01003340 return "contains string: " + Catch::toString( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003341 }
3342 };
3343
Phil Nasha8c65432013-02-19 08:46:09 +00003344 struct StartsWith : StringHolder<StartsWith> {
Phil Nash78d95a02012-03-04 21:22:36 +00003345 StartsWith( NSString* substr ) : StringHolder( substr ){}
3346
Phil Nasha8c65432013-02-19 08:46:09 +00003347 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003348 return (str != nil || m_substr == nil ) &&
3349 [str rangeOfString:m_substr].location == 0;
Phil Nash78d95a02012-03-04 21:22:36 +00003350 }
3351
Phil Nasha8c65432013-02-19 08:46:09 +00003352 virtual std::string toString() const {
Phil Nashacdd3b52014-06-30 07:35:36 +01003353 return "starts with: " + Catch::toString( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003354 }
3355 };
Phil Nasha8c65432013-02-19 08:46:09 +00003356 struct EndsWith : StringHolder<EndsWith> {
Phil Nash78d95a02012-03-04 21:22:36 +00003357 EndsWith( NSString* substr ) : StringHolder( substr ){}
3358
Phil Nasha8c65432013-02-19 08:46:09 +00003359 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003360 return (str != nil || m_substr == nil ) &&
3361 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
Phil Nash78d95a02012-03-04 21:22:36 +00003362 }
3363
Phil Nasha8c65432013-02-19 08:46:09 +00003364 virtual std::string toString() const {
Phil Nashacdd3b52014-06-30 07:35:36 +01003365 return "ends with: " + Catch::toString( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003366 }
3367 };
3368
3369 } // namespace NSStringMatchers
3370 } // namespace Impl
3371
Phil Nash8d18d162012-03-14 20:06:14 +00003372 inline Impl::NSStringMatchers::Equals
3373 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
3374
Phil Nash78d95a02012-03-04 21:22:36 +00003375 inline Impl::NSStringMatchers::Contains
3376 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00003377
Phil Nash78d95a02012-03-04 21:22:36 +00003378 inline Impl::NSStringMatchers::StartsWith
3379 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00003380
Phil Nash78d95a02012-03-04 21:22:36 +00003381 inline Impl::NSStringMatchers::EndsWith
3382 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
3383
3384 } // namespace Matchers
3385
3386 using namespace Matchers;
3387
3388} // namespace Catch
Phil Nash83224e62011-08-12 18:53:28 +01003389
3390///////////////////////////////////////////////////////////////////////////////
3391#define OC_TEST_CASE( name, desc )\
Phil Nash53c990a2012-03-17 18:20:06 +00003392+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01003393{\
Phil Nash53c990a2012-03-17 18:20:06 +00003394return @ name; \
Phil Nash83224e62011-08-12 18:53:28 +01003395}\
Phil Nash53c990a2012-03-17 18:20:06 +00003396+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01003397{ \
Phil Nash53c990a2012-03-17 18:20:06 +00003398return @ desc; \
Phil Nash83224e62011-08-12 18:53:28 +01003399} \
3400-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3401
3402#endif
3403
Phil Nash576aff62014-12-21 00:21:23 +00003404#ifdef CATCH_IMPL
Phil Nash0952b762017-02-28 14:19:09 +00003405
3406// !TBD: Move the leak detector code into a separate header
3407#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
3408#include <crtdbg.h>
3409class LeakDetector {
3410public:
3411 LeakDetector() {
3412 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
3413 flag |= _CRTDBG_LEAK_CHECK_DF;
3414 flag |= _CRTDBG_ALLOC_MEM_DF;
3415 _CrtSetDbgFlag(flag);
3416 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3417 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3418 // Change this to leaking allocation's number to break there
3419 _CrtSetBreakAlloc(-1);
3420 }
3421};
3422#else
3423class LeakDetector {};
3424#endif
3425
3426LeakDetector leakDetector;
3427
Phil Nasha695eb92012-08-13 07:46:10 +01003428// #included from: internal/catch_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003429#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003430
3431// Collect all the implementation files together here
3432// These are the equivalent of what would usually be cpp files
3433
Phil Nash5bc030d2012-08-16 18:48:50 +01003434#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01003435#pragma clang diagnostic push
3436#pragma clang diagnostic ignored "-Wweak-vtables"
Phil Nash5bc030d2012-08-16 18:48:50 +01003437#endif
Phil Nasha695eb92012-08-13 07:46:10 +01003438
Phil Nashe73583d2015-08-07 17:30:34 +01003439// #included from: ../catch_session.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003440#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
Phil Nash83224e62011-08-12 18:53:28 +01003441
Phil Nasha695eb92012-08-13 07:46:10 +01003442// #included from: internal/catch_commandline.hpp
3443#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3444
Phil Nash3649fdf2013-12-03 18:53:55 +00003445// #included from: catch_config.hpp
3446#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3447
Phil Nash65cc14c2014-05-16 18:54:48 +01003448// #included from: catch_test_spec_parser.hpp
3449#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
Phil Nash3649fdf2013-12-03 18:53:55 +00003450
3451#ifdef __clang__
Phil Nash65cc14c2014-05-16 18:54:48 +01003452#pragma clang diagnostic push
Phil Nash3649fdf2013-12-03 18:53:55 +00003453#pragma clang diagnostic ignored "-Wpadded"
3454#endif
3455
Phil Nash65cc14c2014-05-16 18:54:48 +01003456// #included from: catch_test_spec.hpp
3457#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
Phil Nash3649fdf2013-12-03 18:53:55 +00003458
Phil Nash65cc14c2014-05-16 18:54:48 +01003459#ifdef __clang__
3460#pragma clang diagnostic push
3461#pragma clang diagnostic ignored "-Wpadded"
3462#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00003463
Phil Nash8342ae82015-07-13 15:03:26 +01003464// #included from: catch_wildcard_pattern.hpp
3465#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3466
Phil Nashd08cee22017-02-13 16:15:42 +00003467#include <stdexcept>
3468
Phil Nash8342ae82015-07-13 15:03:26 +01003469namespace Catch
3470{
3471 class WildcardPattern {
3472 enum WildcardPosition {
3473 NoWildcard = 0,
3474 WildcardAtStart = 1,
3475 WildcardAtEnd = 2,
3476 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3477 };
3478
3479 public:
3480
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003481 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
Phil Nash8342ae82015-07-13 15:03:26 +01003482 : m_caseSensitivity( caseSensitivity ),
3483 m_wildcard( NoWildcard ),
3484 m_pattern( adjustCase( pattern ) )
3485 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003486 if( startsWith( m_pattern, '*' ) ) {
Phil Nash8342ae82015-07-13 15:03:26 +01003487 m_pattern = m_pattern.substr( 1 );
3488 m_wildcard = WildcardAtStart;
3489 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003490 if( endsWith( m_pattern, '*' ) ) {
Phil Nash8342ae82015-07-13 15:03:26 +01003491 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
3492 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
3493 }
3494 }
3495 virtual ~WildcardPattern();
3496 virtual bool matches( std::string const& str ) const {
3497 switch( m_wildcard ) {
3498 case NoWildcard:
3499 return m_pattern == adjustCase( str );
3500 case WildcardAtStart:
3501 return endsWith( adjustCase( str ), m_pattern );
3502 case WildcardAtEnd:
3503 return startsWith( adjustCase( str ), m_pattern );
3504 case WildcardAtBothEnds:
3505 return contains( adjustCase( str ), m_pattern );
3506 }
3507
3508#ifdef __clang__
3509#pragma clang diagnostic push
3510#pragma clang diagnostic ignored "-Wunreachable-code"
3511#endif
3512 throw std::logic_error( "Unknown enum" );
3513#ifdef __clang__
3514#pragma clang diagnostic pop
3515#endif
3516 }
3517 private:
3518 std::string adjustCase( std::string const& str ) const {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003519 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
Phil Nash8342ae82015-07-13 15:03:26 +01003520 }
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003521 CaseSensitive::Choice m_caseSensitivity;
Phil Nash8342ae82015-07-13 15:03:26 +01003522 WildcardPosition m_wildcard;
3523 std::string m_pattern;
3524 };
3525}
3526
Phil Nash3649fdf2013-12-03 18:53:55 +00003527#include <string>
3528#include <vector>
3529
3530namespace Catch {
3531
Phil Nash65cc14c2014-05-16 18:54:48 +01003532 class TestSpec {
3533 struct Pattern : SharedImpl<> {
3534 virtual ~Pattern();
3535 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
3536 };
3537 class NamePattern : public Pattern {
Phil Nash65cc14c2014-05-16 18:54:48 +01003538 public:
Phil Nash8342ae82015-07-13 15:03:26 +01003539 NamePattern( std::string const& name )
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003540 : m_wildcardPattern( toLower( name ), CaseSensitive::No )
Phil Nash8342ae82015-07-13 15:03:26 +01003541 {}
Phil Nash65cc14c2014-05-16 18:54:48 +01003542 virtual ~NamePattern();
3543 virtual bool matches( TestCaseInfo const& testCase ) const {
Phil Nash8342ae82015-07-13 15:03:26 +01003544 return m_wildcardPattern.matches( toLower( testCase.name ) );
Phil Nash65cc14c2014-05-16 18:54:48 +01003545 }
3546 private:
Phil Nash8342ae82015-07-13 15:03:26 +01003547 WildcardPattern m_wildcardPattern;
Phil Nash65cc14c2014-05-16 18:54:48 +01003548 };
Phil Nash8342ae82015-07-13 15:03:26 +01003549
Phil Nash65cc14c2014-05-16 18:54:48 +01003550 class TagPattern : public Pattern {
3551 public:
3552 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
3553 virtual ~TagPattern();
3554 virtual bool matches( TestCaseInfo const& testCase ) const {
Phil Nash9241e432014-05-20 18:50:59 +01003555 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
Phil Nash65cc14c2014-05-16 18:54:48 +01003556 }
3557 private:
3558 std::string m_tag;
3559 };
Phil Nash8342ae82015-07-13 15:03:26 +01003560
Phil Nash65cc14c2014-05-16 18:54:48 +01003561 class ExcludedPattern : public Pattern {
3562 public:
3563 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
3564 virtual ~ExcludedPattern();
3565 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
3566 private:
3567 Ptr<Pattern> m_underlyingPattern;
3568 };
Phil Nash3649fdf2013-12-03 18:53:55 +00003569
Phil Nash65cc14c2014-05-16 18:54:48 +01003570 struct Filter {
3571 std::vector<Ptr<Pattern> > m_patterns;
3572
3573 bool matches( TestCaseInfo const& testCase ) const {
3574 // All patterns in a filter must match for the filter to be a match
Phil Nash40f60682016-09-27 10:46:22 +01003575 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 +01003576 if( !(*it)->matches( testCase ) )
3577 return false;
Phil Nash40f60682016-09-27 10:46:22 +01003578 }
3579 return true;
Phil Nash65cc14c2014-05-16 18:54:48 +01003580 }
Phil Nash3649fdf2013-12-03 18:53:55 +00003581 };
3582
3583 public:
Phil Nash65cc14c2014-05-16 18:54:48 +01003584 bool hasFilters() const {
3585 return !m_filters.empty();
3586 }
3587 bool matches( TestCaseInfo const& testCase ) const {
3588 // A TestSpec matches if any filter matches
3589 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
3590 if( it->matches( testCase ) )
3591 return true;
3592 return false;
3593 }
Phil Nash3649fdf2013-12-03 18:53:55 +00003594
3595 private:
Phil Nash65cc14c2014-05-16 18:54:48 +01003596 std::vector<Filter> m_filters;
Phil Nash3649fdf2013-12-03 18:53:55 +00003597
Phil Nash65cc14c2014-05-16 18:54:48 +01003598 friend class TestSpecParser;
Phil Nash3649fdf2013-12-03 18:53:55 +00003599 };
Phil Nash3649fdf2013-12-03 18:53:55 +00003600}
3601
Phil Nash65cc14c2014-05-16 18:54:48 +01003602#ifdef __clang__
3603#pragma clang diagnostic pop
3604#endif
3605
3606namespace Catch {
3607
3608 class TestSpecParser {
Phil Nash3b2f2062017-01-11 16:43:56 +00003609 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
Phil Nash65cc14c2014-05-16 18:54:48 +01003610 Mode m_mode;
3611 bool m_exclusion;
3612 std::size_t m_start, m_pos;
3613 std::string m_arg;
Phil Nash3b2f2062017-01-11 16:43:56 +00003614 std::vector<std::size_t> m_escapeChars;
Phil Nash65cc14c2014-05-16 18:54:48 +01003615 TestSpec::Filter m_currentFilter;
3616 TestSpec m_testSpec;
Phil Nash52e1e742014-07-03 08:11:38 +01003617 ITagAliasRegistry const* m_tagAliases;
Phil Nash65cc14c2014-05-16 18:54:48 +01003618
3619 public:
Phil Nash52e1e742014-07-03 08:11:38 +01003620 TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
Phil Nashacdd3b52014-06-30 07:35:36 +01003621
3622 TestSpecParser& parse( std::string const& arg ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01003623 m_mode = None;
3624 m_exclusion = false;
3625 m_start = std::string::npos;
Phil Nash52e1e742014-07-03 08:11:38 +01003626 m_arg = m_tagAliases->expandAliases( arg );
Phil Nash3b2f2062017-01-11 16:43:56 +00003627 m_escapeChars.clear();
Phil Nash65cc14c2014-05-16 18:54:48 +01003628 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
3629 visitChar( m_arg[m_pos] );
3630 if( m_mode == Name )
3631 addPattern<TestSpec::NamePattern>();
3632 return *this;
3633 }
3634 TestSpec testSpec() {
Phil Nash9241e432014-05-20 18:50:59 +01003635 addFilter();
Phil Nash65cc14c2014-05-16 18:54:48 +01003636 return m_testSpec;
3637 }
3638 private:
3639 void visitChar( char c ) {
3640 if( m_mode == None ) {
3641 switch( c ) {
3642 case ' ': return;
3643 case '~': m_exclusion = true; return;
3644 case '[': return startNewMode( Tag, ++m_pos );
3645 case '"': return startNewMode( QuotedName, ++m_pos );
Phil Nash3b2f2062017-01-11 16:43:56 +00003646 case '\\': return escape();
Phil Nash65cc14c2014-05-16 18:54:48 +01003647 default: startNewMode( Name, m_pos ); break;
3648 }
3649 }
3650 if( m_mode == Name ) {
3651 if( c == ',' ) {
3652 addPattern<TestSpec::NamePattern>();
3653 addFilter();
3654 }
3655 else if( c == '[' ) {
3656 if( subString() == "exclude:" )
3657 m_exclusion = true;
3658 else
3659 addPattern<TestSpec::NamePattern>();
3660 startNewMode( Tag, ++m_pos );
3661 }
Phil Nash3b2f2062017-01-11 16:43:56 +00003662 else if( c == '\\' )
3663 escape();
Phil Nash65cc14c2014-05-16 18:54:48 +01003664 }
Phil Nash3b2f2062017-01-11 16:43:56 +00003665 else if( m_mode == EscapedName )
3666 m_mode = Name;
Phil Nash65cc14c2014-05-16 18:54:48 +01003667 else if( m_mode == QuotedName && c == '"' )
3668 addPattern<TestSpec::NamePattern>();
3669 else if( m_mode == Tag && c == ']' )
3670 addPattern<TestSpec::TagPattern>();
3671 }
3672 void startNewMode( Mode mode, std::size_t start ) {
3673 m_mode = mode;
3674 m_start = start;
3675 }
Phil Nash3b2f2062017-01-11 16:43:56 +00003676 void escape() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003677 if( m_mode == None )
3678 m_start = m_pos;
Phil Nash3b2f2062017-01-11 16:43:56 +00003679 m_mode = EscapedName;
3680 m_escapeChars.push_back( m_pos );
3681 }
Phil Nash65cc14c2014-05-16 18:54:48 +01003682 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
3683 template<typename T>
3684 void addPattern() {
3685 std::string token = subString();
Phil Nash3b2f2062017-01-11 16:43:56 +00003686 for( size_t i = 0; i < m_escapeChars.size(); ++i )
Phil Nash0952b762017-02-28 14:19:09 +00003687 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 +00003688 m_escapeChars.clear();
Phil Nash65cc14c2014-05-16 18:54:48 +01003689 if( startsWith( token, "exclude:" ) ) {
3690 m_exclusion = true;
3691 token = token.substr( 8 );
3692 }
3693 if( !token.empty() ) {
3694 Ptr<TestSpec::Pattern> pattern = new T( token );
3695 if( m_exclusion )
3696 pattern = new TestSpec::ExcludedPattern( pattern );
3697 m_currentFilter.m_patterns.push_back( pattern );
3698 }
3699 m_exclusion = false;
3700 m_mode = None;
3701 }
3702 void addFilter() {
3703 if( !m_currentFilter.m_patterns.empty() ) {
3704 m_testSpec.m_filters.push_back( m_currentFilter );
3705 m_currentFilter = TestSpec::Filter();
3706 }
3707 }
3708 };
3709 inline TestSpec parseTestSpec( std::string const& arg ) {
Phil Nashacdd3b52014-06-30 07:35:36 +01003710 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
Phil Nash65cc14c2014-05-16 18:54:48 +01003711 }
3712
3713} // namespace Catch
3714
3715#ifdef __clang__
3716#pragma clang diagnostic pop
3717#endif
3718
Phil Nashab036682014-06-02 07:48:03 +01003719// #included from: catch_interfaces_config.h
3720#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3721
Phil Nashd08cee22017-02-13 16:15:42 +00003722#include <iosfwd>
Phil Nashab036682014-06-02 07:48:03 +01003723#include <string>
3724#include <vector>
3725
3726namespace Catch {
3727
3728 struct Verbosity { enum Level {
3729 NoOutput = 0,
3730 Quiet,
3731 Normal
3732 }; };
3733
3734 struct WarnAbout { enum What {
3735 Nothing = 0x00,
3736 NoAssertions = 0x01
3737 }; };
3738
3739 struct ShowDurations { enum OrNot {
3740 DefaultForReporter,
3741 Always,
3742 Never
3743 }; };
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003744 struct RunTests { enum InWhatOrder {
3745 InDeclarationOrder,
3746 InLexicographicalOrder,
3747 InRandomOrder
3748 }; };
Phil Nashae5ee2c2016-02-29 08:17:18 +00003749 struct UseColour { enum YesOrNo {
3750 Auto,
3751 Yes,
3752 No
3753 }; };
Phil Nashab036682014-06-02 07:48:03 +01003754
3755 class TestSpec;
3756
3757 struct IConfig : IShared {
3758
3759 virtual ~IConfig();
3760
3761 virtual bool allowThrows() const = 0;
3762 virtual std::ostream& stream() const = 0;
3763 virtual std::string name() const = 0;
3764 virtual bool includeSuccessfulResults() const = 0;
3765 virtual bool shouldDebugBreak() const = 0;
3766 virtual bool warnAboutMissingAssertions() const = 0;
3767 virtual int abortAfter() const = 0;
3768 virtual bool showInvisibles() const = 0;
3769 virtual ShowDurations::OrNot showDurations() const = 0;
3770 virtual TestSpec const& testSpec() const = 0;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003771 virtual RunTests::InWhatOrder runOrder() const = 0;
3772 virtual unsigned int rngSeed() const = 0;
Phil Nashae5ee2c2016-02-29 08:17:18 +00003773 virtual UseColour::YesOrNo useColour() const = 0;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003774 virtual std::vector<std::string> const& getSectionsToRun() const = 0;
3775
Phil Nashab036682014-06-02 07:48:03 +01003776 };
3777}
3778
Phil Nash3649fdf2013-12-03 18:53:55 +00003779// #included from: catch_stream.h
3780#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3781
Phil Nash7e346192015-11-03 08:00:43 +00003782// #included from: catch_streambuf.h
3783#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
Phil Nash3649fdf2013-12-03 18:53:55 +00003784
Phil Nash7e346192015-11-03 08:00:43 +00003785#include <streambuf>
Phil Nash3649fdf2013-12-03 18:53:55 +00003786
3787namespace Catch {
3788
Phil Nash7e346192015-11-03 08:00:43 +00003789 class StreamBufBase : public std::streambuf {
Phil Nash3649fdf2013-12-03 18:53:55 +00003790 public:
Phil Nash7e346192015-11-03 08:00:43 +00003791 virtual ~StreamBufBase() CATCH_NOEXCEPT;
Phil Nash3649fdf2013-12-03 18:53:55 +00003792 };
Phil Nash7e346192015-11-03 08:00:43 +00003793}
3794
3795#include <streambuf>
3796#include <ostream>
3797#include <fstream>
Phil Nash2be37272016-11-29 12:15:50 +00003798#include <memory>
Phil Nash7e346192015-11-03 08:00:43 +00003799
3800namespace Catch {
Phil Nash383d7c02014-10-02 19:08:19 +01003801
3802 std::ostream& cout();
3803 std::ostream& cerr();
Phil Nash7e346192015-11-03 08:00:43 +00003804
3805 struct IStream {
3806 virtual ~IStream() CATCH_NOEXCEPT;
3807 virtual std::ostream& stream() const = 0;
3808 };
3809
3810 class FileStream : public IStream {
3811 mutable std::ofstream m_ofs;
3812 public:
3813 FileStream( std::string const& filename );
Phil Nashece529a2015-11-03 17:37:43 +00003814 virtual ~FileStream() CATCH_NOEXCEPT;
Phil Nash7e346192015-11-03 08:00:43 +00003815 public: // IStream
3816 virtual std::ostream& stream() const CATCH_OVERRIDE;
3817 };
3818
3819 class CoutStream : public IStream {
3820 mutable std::ostream m_os;
3821 public:
3822 CoutStream();
Phil Nashece529a2015-11-03 17:37:43 +00003823 virtual ~CoutStream() CATCH_NOEXCEPT;
Phil Nash7e346192015-11-03 08:00:43 +00003824
3825 public: // IStream
3826 virtual std::ostream& stream() const CATCH_OVERRIDE;
3827 };
3828
3829 class DebugOutStream : public IStream {
Phil Nashac220282016-06-09 08:19:23 +01003830 CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
Phil Nash7e346192015-11-03 08:00:43 +00003831 mutable std::ostream m_os;
3832 public:
3833 DebugOutStream();
Phil Nashece529a2015-11-03 17:37:43 +00003834 virtual ~DebugOutStream() CATCH_NOEXCEPT;
Phil Nash7e346192015-11-03 08:00:43 +00003835
3836 public: // IStream
3837 virtual std::ostream& stream() const CATCH_OVERRIDE;
3838 };
Phil Nash3649fdf2013-12-03 18:53:55 +00003839}
3840
3841#include <memory>
3842#include <vector>
3843#include <string>
Phil Nashd08cee22017-02-13 16:15:42 +00003844#include <stdexcept>
Phil Nash3649fdf2013-12-03 18:53:55 +00003845
3846#ifndef CATCH_CONFIG_CONSOLE_WIDTH
3847#define CATCH_CONFIG_CONSOLE_WIDTH 80
3848#endif
3849
3850namespace Catch {
3851
3852 struct ConfigData {
3853
3854 ConfigData()
3855 : listTests( false ),
3856 listTags( false ),
3857 listReporters( false ),
3858 listTestNamesOnly( false ),
3859 showSuccessfulTests( false ),
3860 shouldDebugBreak( false ),
3861 noThrow( false ),
3862 showHelp( false ),
Phil Nashaef6cd52014-04-23 07:10:10 +01003863 showInvisibles( false ),
Phil Nashb971fe72015-07-02 08:21:38 +01003864 filenamesAsTags( false ),
Phil Nash3649fdf2013-12-03 18:53:55 +00003865 abortAfter( -1 ),
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003866 rngSeed( 0 ),
Phil Nash3649fdf2013-12-03 18:53:55 +00003867 verbosity( Verbosity::Normal ),
3868 warnings( WarnAbout::Nothing ),
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003869 showDurations( ShowDurations::DefaultForReporter ),
Phil Nashae5ee2c2016-02-29 08:17:18 +00003870 runOrder( RunTests::InDeclarationOrder ),
3871 useColour( UseColour::Auto )
Phil Nash3649fdf2013-12-03 18:53:55 +00003872 {}
3873
3874 bool listTests;
3875 bool listTags;
3876 bool listReporters;
3877 bool listTestNamesOnly;
3878
3879 bool showSuccessfulTests;
3880 bool shouldDebugBreak;
3881 bool noThrow;
3882 bool showHelp;
Phil Nashaef6cd52014-04-23 07:10:10 +01003883 bool showInvisibles;
Phil Nashb971fe72015-07-02 08:21:38 +01003884 bool filenamesAsTags;
Phil Nash3649fdf2013-12-03 18:53:55 +00003885
3886 int abortAfter;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003887 unsigned int rngSeed;
Phil Nash3649fdf2013-12-03 18:53:55 +00003888
3889 Verbosity::Level verbosity;
3890 WarnAbout::What warnings;
3891 ShowDurations::OrNot showDurations;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003892 RunTests::InWhatOrder runOrder;
Phil Nashae5ee2c2016-02-29 08:17:18 +00003893 UseColour::YesOrNo useColour;
Phil Nash3649fdf2013-12-03 18:53:55 +00003894
Phil Nash3649fdf2013-12-03 18:53:55 +00003895 std::string outputFilename;
3896 std::string name;
3897 std::string processName;
3898
Phil Nashe73583d2015-08-07 17:30:34 +01003899 std::vector<std::string> reporterNames;
Phil Nash3649fdf2013-12-03 18:53:55 +00003900 std::vector<std::string> testsOrTags;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003901 std::vector<std::string> sectionsToRun;
Phil Nash3649fdf2013-12-03 18:53:55 +00003902 };
3903
3904 class Config : public SharedImpl<IConfig> {
3905 private:
3906 Config( Config const& other );
3907 Config& operator = ( Config const& other );
3908 virtual void dummy();
3909 public:
3910
3911 Config()
Phil Nash3649fdf2013-12-03 18:53:55 +00003912 {}
3913
3914 Config( ConfigData const& data )
3915 : m_data( data ),
Phil Nash7e346192015-11-03 08:00:43 +00003916 m_stream( openStream() )
Phil Nash3649fdf2013-12-03 18:53:55 +00003917 {
3918 if( !data.testsOrTags.empty() ) {
Phil Nashacdd3b52014-06-30 07:35:36 +01003919 TestSpecParser parser( ITagAliasRegistry::get() );
Phil Nash65cc14c2014-05-16 18:54:48 +01003920 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
3921 parser.parse( data.testsOrTags[i] );
3922 m_testSpec = parser.testSpec();
Phil Nash3649fdf2013-12-03 18:53:55 +00003923 }
3924 }
3925
Phil Nashd08cee22017-02-13 16:15:42 +00003926 virtual ~Config() {}
Phil Nash3649fdf2013-12-03 18:53:55 +00003927
3928 std::string const& getFilename() const {
3929 return m_data.outputFilename ;
3930 }
3931
3932 bool listTests() const { return m_data.listTests; }
3933 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
3934 bool listTags() const { return m_data.listTags; }
3935 bool listReporters() const { return m_data.listReporters; }
3936
Phil Nash65cc14c2014-05-16 18:54:48 +01003937 std::string getProcessName() const { return m_data.processName; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003938
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003939 std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; }
3940 std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003941
Phil Nashd08cee22017-02-13 16:15:42 +00003942 virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003943
3944 bool showHelp() const { return m_data.showHelp; }
3945
3946 // IConfig interface
Phil Nashd08cee22017-02-13 16:15:42 +00003947 virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; }
3948 virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); }
3949 virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; }
3950 virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; }
3951 virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; }
3952 virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; }
3953 virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; }
3954 virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; }
3955 virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; }
3956 virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; }
3957 virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; }
3958 virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003959
3960 private:
Phil Nash7e346192015-11-03 08:00:43 +00003961
3962 IStream const* openStream() {
3963 if( m_data.outputFilename.empty() )
3964 return new CoutStream();
3965 else if( m_data.outputFilename[0] == '%' ) {
3966 if( m_data.outputFilename == "%debug" )
3967 return new DebugOutStream();
3968 else
3969 throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
3970 }
3971 else
3972 return new FileStream( m_data.outputFilename );
3973 }
Phil Nash3649fdf2013-12-03 18:53:55 +00003974 ConfigData m_data;
3975
Phil Nashac220282016-06-09 08:19:23 +01003976 CATCH_AUTO_PTR( IStream const ) m_stream;
Phil Nash65cc14c2014-05-16 18:54:48 +01003977 TestSpec m_testSpec;
Phil Nash3649fdf2013-12-03 18:53:55 +00003978 };
3979
3980} // end namespace Catch
3981
Phil Nash1c2fbe12014-02-11 18:12:41 +00003982// #included from: catch_clara.h
3983#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
3984
Phil Nashb9fea752014-03-06 08:16:06 +00003985// Use Catch's value for console width (store Clara's off to the side, if present)
3986#ifdef CLARA_CONFIG_CONSOLE_WIDTH
3987#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
3988#undef CLARA_CONFIG_CONSOLE_WIDTH
3989#endif
Phil Nash1c2fbe12014-02-11 18:12:41 +00003990#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
3991
3992// Declare Clara inside the Catch namespace
Phil Nashb9fea752014-03-06 08:16:06 +00003993#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
Phil Nash472dc2a2014-03-17 18:40:58 +00003994// #included from: ../external/clara.h
Phil Nasha695eb92012-08-13 07:46:10 +01003995
Phil Nash5c198d82016-05-07 23:14:04 +01003996// Version 0.0.2.4
Phil Nash3b4edd72016-02-10 19:24:48 +00003997
Phil Nash1c2fbe12014-02-11 18:12:41 +00003998// Only use header guard if we are not using an outer namespace
Phil Nashb9fea752014-03-06 08:16:06 +00003999#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
4000
4001#ifndef STITCH_CLARA_OPEN_NAMESPACE
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004002#define TWOBLUECUBES_CLARA_H_INCLUDED
Phil Nashb9fea752014-03-06 08:16:06 +00004003#define STITCH_CLARA_OPEN_NAMESPACE
4004#define STITCH_CLARA_CLOSE_NAMESPACE
4005#else
4006#define STITCH_CLARA_CLOSE_NAMESPACE }
Phil Nash1c2fbe12014-02-11 18:12:41 +00004007#endif
Phil Nash38f7eef2013-03-29 13:44:33 +00004008
Phil Nashb9fea752014-03-06 08:16:06 +00004009#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004010
4011// ----------- #included from tbc_text_format.h -----------
4012
Phil Nash1c2fbe12014-02-11 18:12:41 +00004013// Only use header guard if we are not using an outer namespace
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004014#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
4015#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4016#define TBC_TEXT_FORMAT_H_INCLUDED
Phil Nash1c2fbe12014-02-11 18:12:41 +00004017#endif
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004018
Phil Nash38f7eef2013-03-29 13:44:33 +00004019#include <string>
4020#include <vector>
Phil Nash1c2fbe12014-02-11 18:12:41 +00004021#include <sstream>
Phil Nash3b4edd72016-02-10 19:24:48 +00004022#include <algorithm>
Phil Nash38f7eef2013-03-29 13:44:33 +00004023
Phil Nash1c2fbe12014-02-11 18:12:41 +00004024// Use optional outer namespace
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004025#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4026namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
Phil Nash1c2fbe12014-02-11 18:12:41 +00004027#endif
4028
4029namespace Tbc {
4030
4031#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4032 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4033#else
4034 const unsigned int consoleWidth = 80;
4035#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01004036
Phil Nash19279252013-04-20 21:07:32 +01004037 struct TextAttributes {
4038 TextAttributes()
4039 : initialIndent( std::string::npos ),
4040 indent( 0 ),
Phil Nash1c2fbe12014-02-11 18:12:41 +00004041 width( consoleWidth-1 ),
Phil Nash19279252013-04-20 21:07:32 +01004042 tabChar( '\t' )
Phil Nash89d1e6c2011-05-24 08:23:02 +01004043 {}
Phil Nash3b80af72012-08-09 07:47:30 +01004044
Phil Nash19279252013-04-20 21:07:32 +01004045 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
4046 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
4047 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
4048 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
Phil Nash89d2a3f2012-05-16 15:09:17 +01004049
Phil Nash19279252013-04-20 21:07:32 +01004050 std::size_t initialIndent; // indent of first line, or npos
4051 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
4052 std::size_t width; // maximum width of text, including indent. Longer text will wrap
4053 char tabChar; // If this char is seen the indent is changed to current pos
Phil Nash89d1e6c2011-05-24 08:23:02 +01004054 };
4055
Phil Nash19279252013-04-20 21:07:32 +01004056 class Text {
Phil Nasha695eb92012-08-13 07:46:10 +01004057 public:
Phil Nash1c2fbe12014-02-11 18:12:41 +00004058 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
4059 : attr( _attr )
4060 {
4061 std::string wrappableChars = " [({.,/|\\-";
4062 std::size_t indent = _attr.initialIndent != std::string::npos
4063 ? _attr.initialIndent
4064 : _attr.indent;
4065 std::string remainder = _str;
4066
4067 while( !remainder.empty() ) {
4068 if( lines.size() >= 1000 ) {
4069 lines.push_back( "... message truncated due to excessive size" );
4070 return;
4071 }
4072 std::size_t tabPos = std::string::npos;
4073 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4074 std::size_t pos = remainder.find_first_of( '\n' );
4075 if( pos <= width ) {
4076 width = pos;
4077 }
4078 pos = remainder.find_last_of( _attr.tabChar, width );
4079 if( pos != std::string::npos ) {
4080 tabPos = pos;
4081 if( remainder[width] == '\n' )
4082 width--;
4083 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4084 }
4085
4086 if( width == remainder.size() ) {
4087 spliceLine( indent, remainder, width );
4088 }
4089 else if( remainder[width] == '\n' ) {
4090 spliceLine( indent, remainder, width );
4091 if( width <= 1 || remainder.size() != 1 )
4092 remainder = remainder.substr( 1 );
4093 indent = _attr.indent;
4094 }
4095 else {
4096 pos = remainder.find_last_of( wrappableChars, width );
4097 if( pos != std::string::npos && pos > 0 ) {
4098 spliceLine( indent, remainder, pos );
4099 if( remainder[0] == ' ' )
4100 remainder = remainder.substr( 1 );
4101 }
4102 else {
4103 spliceLine( indent, remainder, width-1 );
4104 lines.back() += "-";
4105 }
4106 if( lines.size() == 1 )
4107 indent = _attr.indent;
4108 if( tabPos != std::string::npos )
4109 indent += tabPos;
4110 }
4111 }
4112 }
4113
4114 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4115 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
4116 _remainder = _remainder.substr( _pos );
4117 }
Phil Nasha695eb92012-08-13 07:46:10 +01004118
Phil Nash38f7eef2013-03-29 13:44:33 +00004119 typedef std::vector<std::string>::const_iterator const_iterator;
Phil Nasha695eb92012-08-13 07:46:10 +01004120
Phil Nash38f7eef2013-03-29 13:44:33 +00004121 const_iterator begin() const { return lines.begin(); }
4122 const_iterator end() const { return lines.end(); }
4123 std::string const& last() const { return lines.back(); }
4124 std::size_t size() const { return lines.size(); }
4125 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
Phil Nash1c2fbe12014-02-11 18:12:41 +00004126 std::string toString() const {
4127 std::ostringstream oss;
4128 oss << *this;
4129 return oss.str();
4130 }
Phil Nasha695eb92012-08-13 07:46:10 +01004131
Phil Nash1c2fbe12014-02-11 18:12:41 +00004132 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
4133 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4134 it != itEnd; ++it ) {
4135 if( it != _text.begin() )
4136 _stream << "\n";
4137 _stream << *it;
4138 }
4139 return _stream;
4140 }
Phil Nasha695eb92012-08-13 07:46:10 +01004141
Phil Nasha695eb92012-08-13 07:46:10 +01004142 private:
Phil Nash19279252013-04-20 21:07:32 +01004143 std::string str;
4144 TextAttributes attr;
Phil Nash38f7eef2013-03-29 13:44:33 +00004145 std::vector<std::string> lines;
4146 };
4147
Phil Nash1c2fbe12014-02-11 18:12:41 +00004148} // end namespace Tbc
4149
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004150#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
Phil Nash1c2fbe12014-02-11 18:12:41 +00004151} // end outer namespace
4152#endif
4153
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004154#endif // TBC_TEXT_FORMAT_H_INCLUDED
Phil Nash1c2fbe12014-02-11 18:12:41 +00004155
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004156// ----------- end of #include from tbc_text_format.h -----------
Phil Nash3b4edd72016-02-10 19:24:48 +00004157// ........... back in clara.h
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004158
Phil Nashb9fea752014-03-06 08:16:06 +00004159#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004160
Phil Nash3b4edd72016-02-10 19:24:48 +00004161// ----------- #included from clara_compilers.h -----------
4162
4163#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4164#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4165
4166// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
4167// The following features are defined:
4168//
4169// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
4170// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
4171// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
4172// CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
4173// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
4174
4175// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
4176
4177// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
4178
4179// In general each macro has a _NO_<feature name> form
4180// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
4181// Many features, at point of detection, define an _INTERNAL_ macro, so they
4182// can be combined, en-mass, with the _NO_ forms later.
4183
4184// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
4185
4186#ifdef __clang__
4187
4188#if __has_feature(cxx_nullptr)
4189#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4190#endif
4191
4192#if __has_feature(cxx_noexcept)
4193#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4194#endif
4195
4196#endif // __clang__
4197
4198////////////////////////////////////////////////////////////////////////////////
4199// GCC
4200#ifdef __GNUC__
4201
4202#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
4203#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4204#endif
4205
4206// - otherwise more recent versions define __cplusplus >= 201103L
4207// and will get picked up below
4208
4209#endif // __GNUC__
4210
4211////////////////////////////////////////////////////////////////////////////////
4212// Visual C++
4213#ifdef _MSC_VER
4214
4215#if (_MSC_VER >= 1600)
4216#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4217#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
4218#endif
4219
4220#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
4221#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4222#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4223#endif
4224
4225#endif // _MSC_VER
4226
4227////////////////////////////////////////////////////////////////////////////////
4228// C++ language feature support
4229
4230// catch all support for C++11
4231#if defined(__cplusplus) && __cplusplus >= 201103L
4232
4233#define CLARA_CPP11_OR_GREATER
4234
4235#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
4236#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4237#endif
4238
4239#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4240#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4241#endif
4242
4243#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4244#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4245#endif
4246
4247#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
4248#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
4249#endif
4250#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
4251#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
4252#endif
4253
4254#endif // __cplusplus >= 201103L
4255
4256// Now set the actual defines based on the above + anything the user has configured
4257#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
4258#define CLARA_CONFIG_CPP11_NULLPTR
4259#endif
4260#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
4261#define CLARA_CONFIG_CPP11_NOEXCEPT
4262#endif
4263#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)
4264#define CLARA_CONFIG_CPP11_GENERATED_METHODS
4265#endif
4266#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
4267#define CLARA_CONFIG_CPP11_OVERRIDE
4268#endif
4269#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)
4270#define CLARA_CONFIG_CPP11_UNIQUE_PTR
4271#endif
4272
4273// noexcept support:
4274#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
4275#define CLARA_NOEXCEPT noexcept
4276# define CLARA_NOEXCEPT_IS(x) noexcept(x)
4277#else
4278#define CLARA_NOEXCEPT throw()
4279# define CLARA_NOEXCEPT_IS(x)
4280#endif
4281
4282// nullptr support
4283#ifdef CLARA_CONFIG_CPP11_NULLPTR
4284#define CLARA_NULL nullptr
4285#else
4286#define CLARA_NULL NULL
4287#endif
4288
4289// override support
4290#ifdef CLARA_CONFIG_CPP11_OVERRIDE
4291#define CLARA_OVERRIDE override
4292#else
4293#define CLARA_OVERRIDE
4294#endif
4295
4296// unique_ptr support
4297#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
4298# define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
4299#else
4300# define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
4301#endif
4302
4303#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4304
4305// ----------- end of #include from clara_compilers.h -----------
4306// ........... back in clara.h
4307
Phil Nash1c2fbe12014-02-11 18:12:41 +00004308#include <map>
Phil Nash1c2fbe12014-02-11 18:12:41 +00004309#include <stdexcept>
4310#include <memory>
4311
Phil Nashe5537842016-04-25 18:56:50 +01004312#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
4313#define CLARA_PLATFORM_WINDOWS
4314#endif
4315
Phil Nash1c2fbe12014-02-11 18:12:41 +00004316// Use optional outer namespace
Phil Nashb9fea752014-03-06 08:16:06 +00004317#ifdef STITCH_CLARA_OPEN_NAMESPACE
4318STITCH_CLARA_OPEN_NAMESPACE
Phil Nash1c2fbe12014-02-11 18:12:41 +00004319#endif
Phil Nash38f7eef2013-03-29 13:44:33 +00004320
Phil Nash786959d2013-06-07 19:07:50 +01004321namespace Clara {
Phil Nashb9fea752014-03-06 08:16:06 +00004322
4323 struct UnpositionalTag {};
4324
4325 extern UnpositionalTag _;
4326
4327#ifdef CLARA_CONFIG_MAIN
4328 UnpositionalTag _;
4329#endif
4330
Phil Nash786959d2013-06-07 19:07:50 +01004331 namespace Detail {
Phil Nash1c2fbe12014-02-11 18:12:41 +00004332
4333#ifdef CLARA_CONSOLE_WIDTH
4334 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
4335#else
4336 const unsigned int consoleWidth = 80;
4337#endif
4338
Phil Nashb9fea752014-03-06 08:16:06 +00004339 using namespace Tbc;
4340
4341 inline bool startsWith( std::string const& str, std::string const& prefix ) {
4342 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
4343 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00004344
Phil Nash786959d2013-06-07 19:07:50 +01004345 template<typename T> struct RemoveConstRef{ typedef T type; };
4346 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
4347 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
4348 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
4349
4350 template<typename T> struct IsBool { static const bool value = false; };
4351 template<> struct IsBool<bool> { static const bool value = true; };
Phil Nasha695eb92012-08-13 07:46:10 +01004352
4353 template<typename T>
Phil Nash786959d2013-06-07 19:07:50 +01004354 void convertInto( std::string const& _source, T& _dest ) {
4355 std::stringstream ss;
4356 ss << _source;
4357 ss >> _dest;
4358 if( ss.fail() )
4359 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
Phil Nasha695eb92012-08-13 07:46:10 +01004360 }
Phil Nash786959d2013-06-07 19:07:50 +01004361 inline void convertInto( std::string const& _source, std::string& _dest ) {
4362 _dest = _source;
4363 }
Phil Nash2be37272016-11-29 12:15:50 +00004364 char toLowerCh(char c) {
4365 return static_cast<char>( ::tolower( c ) );
4366 }
Phil Nash786959d2013-06-07 19:07:50 +01004367 inline void convertInto( std::string const& _source, bool& _dest ) {
4368 std::string sourceLC = _source;
Phil Nash2be37272016-11-29 12:15:50 +00004369 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh );
Phil Nash46118712013-08-16 19:01:32 +01004370 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
Phil Nash786959d2013-06-07 19:07:50 +01004371 _dest = true;
Phil Nash46118712013-08-16 19:01:32 +01004372 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
Phil Nash786959d2013-06-07 19:07:50 +01004373 _dest = false;
4374 else
Phil Nash46118712013-08-16 19:01:32 +01004375 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
Phil Nash786959d2013-06-07 19:07:50 +01004376 }
Phil Nasha695eb92012-08-13 07:46:10 +01004377
Phil Nash786959d2013-06-07 19:07:50 +01004378 template<typename ConfigT>
4379 struct IArgFunction {
4380 virtual ~IArgFunction() {}
Phil Nash3b4edd72016-02-10 19:24:48 +00004381#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01004382 IArgFunction() = default;
4383 IArgFunction( IArgFunction const& ) = default;
Phil Nash3b4edd72016-02-10 19:24:48 +00004384#endif
Phil Nash786959d2013-06-07 19:07:50 +01004385 virtual void set( ConfigT& config, std::string const& value ) const = 0;
Phil Nash786959d2013-06-07 19:07:50 +01004386 virtual bool takesArg() const = 0;
4387 virtual IArgFunction* clone() const = 0;
4388 };
4389
4390 template<typename ConfigT>
4391 class BoundArgFunction {
4392 public:
Phil Nash3b4edd72016-02-10 19:24:48 +00004393 BoundArgFunction() : functionObj( CLARA_NULL ) {}
Phil Nash786959d2013-06-07 19:07:50 +01004394 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
Phil Nash3b4edd72016-02-10 19:24:48 +00004395 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
Phil Nash786959d2013-06-07 19:07:50 +01004396 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
Phil Nash3b4edd72016-02-10 19:24:48 +00004397 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
Phil Nash786959d2013-06-07 19:07:50 +01004398 delete functionObj;
4399 functionObj = newFunctionObj;
4400 return *this;
4401 }
4402 ~BoundArgFunction() { delete functionObj; }
4403
4404 void set( ConfigT& config, std::string const& value ) const {
4405 functionObj->set( config, value );
4406 }
Phil Nash786959d2013-06-07 19:07:50 +01004407 bool takesArg() const { return functionObj->takesArg(); }
Phil Nashaf8cd982014-03-24 18:15:04 +00004408
4409 bool isSet() const {
Phil Nash3b4edd72016-02-10 19:24:48 +00004410 return functionObj != CLARA_NULL;
Phil Nashaf8cd982014-03-24 18:15:04 +00004411 }
Phil Nash786959d2013-06-07 19:07:50 +01004412 private:
4413 IArgFunction<ConfigT>* functionObj;
4414 };
4415
4416 template<typename C>
4417 struct NullBinder : IArgFunction<C>{
4418 virtual void set( C&, std::string const& ) const {}
Phil Nash786959d2013-06-07 19:07:50 +01004419 virtual bool takesArg() const { return true; }
4420 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
4421 };
4422
4423 template<typename C, typename M>
4424 struct BoundDataMember : IArgFunction<C>{
4425 BoundDataMember( M C::* _member ) : member( _member ) {}
4426 virtual void set( C& p, std::string const& stringValue ) const {
4427 convertInto( stringValue, p.*member );
4428 }
Phil Nash786959d2013-06-07 19:07:50 +01004429 virtual bool takesArg() const { return !IsBool<M>::value; }
4430 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
4431 M C::* member;
4432 };
4433 template<typename C, typename M>
4434 struct BoundUnaryMethod : IArgFunction<C>{
4435 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
4436 virtual void set( C& p, std::string const& stringValue ) const {
4437 typename RemoveConstRef<M>::type value;
4438 convertInto( stringValue, value );
4439 (p.*member)( value );
4440 }
Phil Nash786959d2013-06-07 19:07:50 +01004441 virtual bool takesArg() const { return !IsBool<M>::value; }
4442 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
4443 void (C::*member)( M );
4444 };
4445 template<typename C>
4446 struct BoundNullaryMethod : IArgFunction<C>{
4447 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
4448 virtual void set( C& p, std::string const& stringValue ) const {
4449 bool value;
4450 convertInto( stringValue, value );
4451 if( value )
4452 (p.*member)();
4453 }
Phil Nash786959d2013-06-07 19:07:50 +01004454 virtual bool takesArg() const { return false; }
4455 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
4456 void (C::*member)();
4457 };
4458
4459 template<typename C>
4460 struct BoundUnaryFunction : IArgFunction<C>{
4461 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
4462 virtual void set( C& obj, std::string const& stringValue ) const {
4463 bool value;
4464 convertInto( stringValue, value );
4465 if( value )
4466 function( obj );
4467 }
Phil Nash786959d2013-06-07 19:07:50 +01004468 virtual bool takesArg() const { return false; }
4469 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
4470 void (*function)( C& );
4471 };
4472
4473 template<typename C, typename T>
4474 struct BoundBinaryFunction : IArgFunction<C>{
4475 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
4476 virtual void set( C& obj, std::string const& stringValue ) const {
4477 typename RemoveConstRef<T>::type value;
4478 convertInto( stringValue, value );
4479 function( obj, value );
4480 }
Phil Nash786959d2013-06-07 19:07:50 +01004481 virtual bool takesArg() const { return !IsBool<T>::value; }
4482 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
4483 void (*function)( C&, T );
4484 };
4485
Phil Nash786959d2013-06-07 19:07:50 +01004486 } // namespace Detail
4487
Phil Nashe5537842016-04-25 18:56:50 +01004488 inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
4489 std::vector<std::string> args( static_cast<std::size_t>( argc ) );
4490 for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
4491 args[i] = argv[i];
4492
4493 return args;
4494 }
4495
4496 class Parser {
4497 enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
4498 Mode mode;
4499 std::size_t from;
4500 bool inQuotes;
4501 public:
Phil Nash786959d2013-06-07 19:07:50 +01004502
4503 struct Token {
4504 enum Type { Positional, ShortOpt, LongOpt };
4505 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
4506 Type type;
4507 std::string data;
4508 };
4509
Phil Nashe5537842016-04-25 18:56:50 +01004510 Parser() : mode( None ), from( 0 ), inQuotes( false ){}
4511
4512 void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
Phil Nashe45e3a12013-12-23 10:24:06 +00004513 const std::string doubleDash = "--";
Phil Nashe5537842016-04-25 18:56:50 +01004514 for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
4515 parseIntoTokens( args[i], tokens);
Phil Nash786959d2013-06-07 19:07:50 +01004516 }
Phil Nashe5537842016-04-25 18:56:50 +01004517
4518 void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
4519 for( std::size_t i = 0; i <= arg.size(); ++i ) {
4520 char c = arg[i];
4521 if( c == '"' )
4522 inQuotes = !inQuotes;
4523 mode = handleMode( i, c, arg, tokens );
Phil Nash786959d2013-06-07 19:07:50 +01004524 }
4525 }
Phil Nashe5537842016-04-25 18:56:50 +01004526 Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4527 switch( mode ) {
4528 case None: return handleNone( i, c );
4529 case MaybeShortOpt: return handleMaybeShortOpt( i, c );
4530 case ShortOpt:
4531 case LongOpt:
4532 case SlashOpt: return handleOpt( i, c, arg, tokens );
4533 case Positional: return handlePositional( i, c, arg, tokens );
4534 default: throw std::logic_error( "Unknown mode" );
4535 }
4536 }
4537
4538 Mode handleNone( std::size_t i, char c ) {
4539 if( inQuotes ) {
4540 from = i;
4541 return Positional;
4542 }
4543 switch( c ) {
4544 case '-': return MaybeShortOpt;
4545#ifdef CLARA_PLATFORM_WINDOWS
4546 case '/': from = i+1; return SlashOpt;
4547#endif
4548 default: from = i; return Positional;
4549 }
4550 }
4551 Mode handleMaybeShortOpt( std::size_t i, char c ) {
4552 switch( c ) {
4553 case '-': from = i+1; return LongOpt;
4554 default: from = i; return ShortOpt;
4555 }
4556 }
4557 Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
Phil Nash35f51052016-06-09 19:21:09 +01004558 if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
Phil Nashe5537842016-04-25 18:56:50 +01004559 return mode;
4560
4561 std::string optName = arg.substr( from, i-from );
4562 if( mode == ShortOpt )
4563 for( std::size_t j = 0; j < optName.size(); ++j )
4564 tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
4565 else if( mode == SlashOpt && optName.size() == 1 )
4566 tokens.push_back( Token( Token::ShortOpt, optName ) );
4567 else
4568 tokens.push_back( Token( Token::LongOpt, optName ) );
4569 return None;
4570 }
4571 Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
Phil Nash35f51052016-06-09 19:21:09 +01004572 if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
Phil Nashe5537842016-04-25 18:56:50 +01004573 return mode;
4574
4575 std::string data = arg.substr( from, i-from );
4576 tokens.push_back( Token( Token::Positional, data ) );
4577 return None;
4578 }
Phil Nasha695eb92012-08-13 07:46:10 +01004579 };
4580
Phil Nash786959d2013-06-07 19:07:50 +01004581 template<typename ConfigT>
Phil Nash472dc2a2014-03-17 18:40:58 +00004582 struct CommonArgProperties {
4583 CommonArgProperties() {}
4584 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
4585
4586 Detail::BoundArgFunction<ConfigT> boundField;
4587 std::string description;
Phil Nashaf8cd982014-03-24 18:15:04 +00004588 std::string detail;
Phil Nash472dc2a2014-03-17 18:40:58 +00004589 std::string placeholder; // Only value if boundField takes an arg
4590
4591 bool takesArg() const {
4592 return !placeholder.empty();
4593 }
Phil Nashaf8cd982014-03-24 18:15:04 +00004594 void validate() const {
4595 if( !boundField.isSet() )
4596 throw std::logic_error( "option not bound" );
4597 }
Phil Nash472dc2a2014-03-17 18:40:58 +00004598 };
4599 struct OptionArgProperties {
4600 std::vector<std::string> shortNames;
4601 std::string longName;
4602
4603 bool hasShortName( std::string const& shortName ) const {
4604 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
4605 }
4606 bool hasLongName( std::string const& _longName ) const {
4607 return _longName == longName;
4608 }
Phil Nash472dc2a2014-03-17 18:40:58 +00004609 };
4610 struct PositionalArgProperties {
4611 PositionalArgProperties() : position( -1 ) {}
4612 int position; // -1 means non-positional (floating)
4613
4614 bool isFixedPositional() const {
4615 return position != -1;
4616 }
4617 };
4618
4619 template<typename ConfigT>
Phil Nash786959d2013-06-07 19:07:50 +01004620 class CommandLine {
4621
Phil Nash472dc2a2014-03-17 18:40:58 +00004622 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
4623 Arg() {}
4624 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
Phil Nash786959d2013-06-07 19:07:50 +01004625
Phil Nash472dc2a2014-03-17 18:40:58 +00004626 using CommonArgProperties<ConfigT>::placeholder; // !TBD
4627
Phil Nash786959d2013-06-07 19:07:50 +01004628 std::string dbgName() const {
4629 if( !longName.empty() )
4630 return "--" + longName;
4631 if( !shortNames.empty() )
4632 return "-" + shortNames[0];
4633 return "positional args";
4634 }
Phil Nash786959d2013-06-07 19:07:50 +01004635 std::string commands() const {
4636 std::ostringstream oss;
4637 bool first = true;
4638 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4639 for(; it != itEnd; ++it ) {
4640 if( first )
4641 first = false;
4642 else
4643 oss << ", ";
4644 oss << "-" << *it;
4645 }
4646 if( !longName.empty() ) {
4647 if( !first )
4648 oss << ", ";
4649 oss << "--" << longName;
4650 }
Phil Nashb9fea752014-03-06 08:16:06 +00004651 if( !placeholder.empty() )
4652 oss << " <" << placeholder << ">";
Phil Nash786959d2013-06-07 19:07:50 +01004653 return oss.str();
4654 }
Phil Nash786959d2013-06-07 19:07:50 +01004655 };
4656
Phil Nash3b4edd72016-02-10 19:24:48 +00004657 typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
Phil Nash5ecb72b2013-11-26 20:57:45 +00004658
Phil Nash472dc2a2014-03-17 18:40:58 +00004659 friend void addOptName( Arg& arg, std::string const& optName )
4660 {
4661 if( optName.empty() )
4662 return;
4663 if( Detail::startsWith( optName, "--" ) ) {
4664 if( !arg.longName.empty() )
4665 throw std::logic_error( "Only one long opt may be specified. '"
4666 + arg.longName
4667 + "' already specified, now attempting to add '"
4668 + optName + "'" );
4669 arg.longName = optName.substr( 2 );
4670 }
4671 else if( Detail::startsWith( optName, "-" ) )
4672 arg.shortNames.push_back( optName.substr( 1 ) );
4673 else
4674 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
4675 }
4676 friend void setPositionalArg( Arg& arg, int position )
4677 {
4678 arg.position = position;
4679 }
4680
Phil Nashb9fea752014-03-06 08:16:06 +00004681 class ArgBuilder {
Phil Nash786959d2013-06-07 19:07:50 +01004682 public:
Phil Nashaf8cd982014-03-24 18:15:04 +00004683 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
Phil Nashb9fea752014-03-06 08:16:06 +00004684
Phil Nash472dc2a2014-03-17 18:40:58 +00004685 // Bind a non-boolean data member (requires placeholder string)
4686 template<typename C, typename M>
4687 void bind( M C::* field, std::string const& placeholder ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004688 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
4689 m_arg->placeholder = placeholder;
Phil Nash472dc2a2014-03-17 18:40:58 +00004690 }
4691 // Bind a boolean data member (no placeholder required)
4692 template<typename C>
4693 void bind( bool C::* field ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004694 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
Phil Nash472dc2a2014-03-17 18:40:58 +00004695 }
4696
4697 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
4698 template<typename C, typename M>
Phil Nashaf8cd982014-03-24 18:15:04 +00004699 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
4700 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
4701 m_arg->placeholder = placeholder;
Phil Nash472dc2a2014-03-17 18:40:58 +00004702 }
4703
4704 // Bind a method taking a single, boolean argument (no placeholder string required)
4705 template<typename C>
Phil Nashaf8cd982014-03-24 18:15:04 +00004706 void bind( void (C::* unaryMethod)( bool ) ) {
4707 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
Phil Nash472dc2a2014-03-17 18:40:58 +00004708 }
4709
4710 // Bind a method that takes no arguments (will be called if opt is present)
4711 template<typename C>
Phil Nashaf8cd982014-03-24 18:15:04 +00004712 void bind( void (C::* nullaryMethod)() ) {
4713 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
Phil Nash472dc2a2014-03-17 18:40:58 +00004714 }
4715
4716 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
4717 template<typename C>
Phil Nashaf8cd982014-03-24 18:15:04 +00004718 void bind( void (* unaryFunction)( C& ) ) {
4719 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
Phil Nash472dc2a2014-03-17 18:40:58 +00004720 }
4721
4722 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
4723 template<typename C, typename T>
Phil Nashaf8cd982014-03-24 18:15:04 +00004724 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
4725 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
4726 m_arg->placeholder = placeholder;
Phil Nash786959d2013-06-07 19:07:50 +01004727 }
Phil Nashb9fea752014-03-06 08:16:06 +00004728
4729 ArgBuilder& describe( std::string const& description ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004730 m_arg->description = description;
Phil Nash786959d2013-06-07 19:07:50 +01004731 return *this;
4732 }
Phil Nash3b4edd72016-02-10 19:24:48 +00004733 ArgBuilder& detail( std::string const& detail ) {
4734 m_arg->detail = detail;
Phil Nash786959d2013-06-07 19:07:50 +01004735 return *this;
4736 }
Phil Nashb9fea752014-03-06 08:16:06 +00004737
Phil Nash472dc2a2014-03-17 18:40:58 +00004738 protected:
Phil Nashaf8cd982014-03-24 18:15:04 +00004739 Arg* m_arg;
Phil Nash786959d2013-06-07 19:07:50 +01004740 };
Phil Nash472dc2a2014-03-17 18:40:58 +00004741
Phil Nashb9fea752014-03-06 08:16:06 +00004742 class OptBuilder : public ArgBuilder {
4743 public:
Phil Nashaf8cd982014-03-24 18:15:04 +00004744 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
Phil Nashb9fea752014-03-06 08:16:06 +00004745 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
4746
4747 OptBuilder& operator[]( std::string const& optName ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004748 addOptName( *ArgBuilder::m_arg, optName );
Phil Nashb9fea752014-03-06 08:16:06 +00004749 return *this;
4750 }
4751 };
Phil Nash786959d2013-06-07 19:07:50 +01004752
4753 public:
4754
4755 CommandLine()
4756 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
Phil Nash91ef5f72013-12-20 19:06:26 +00004757 m_highestSpecifiedArgPosition( 0 ),
4758 m_throwOnUnrecognisedTokens( false )
Phil Nash786959d2013-06-07 19:07:50 +01004759 {}
4760 CommandLine( CommandLine const& other )
4761 : m_boundProcessName( other.m_boundProcessName ),
4762 m_options ( other.m_options ),
4763 m_positionalArgs( other.m_positionalArgs ),
Phil Nash91ef5f72013-12-20 19:06:26 +00004764 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
4765 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
Phil Nash786959d2013-06-07 19:07:50 +01004766 {
Phil Nash472dc2a2014-03-17 18:40:58 +00004767 if( other.m_floatingArg.get() )
Phil Nash85b4e942014-10-02 18:51:05 +01004768 m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
Phil Nash786959d2013-06-07 19:07:50 +01004769 }
4770
Phil Nash91ef5f72013-12-20 19:06:26 +00004771 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
4772 m_throwOnUnrecognisedTokens = shouldThrow;
4773 return *this;
4774 }
4775
Phil Nashb9fea752014-03-06 08:16:06 +00004776 OptBuilder operator[]( std::string const& optName ) {
Phil Nash472dc2a2014-03-17 18:40:58 +00004777 m_options.push_back( Arg() );
4778 addOptName( m_options.back(), optName );
Phil Nashaf8cd982014-03-24 18:15:04 +00004779 OptBuilder builder( &m_options.back() );
Phil Nashb9fea752014-03-06 08:16:06 +00004780 return builder;
Phil Nash786959d2013-06-07 19:07:50 +01004781 }
Phil Nashb9fea752014-03-06 08:16:06 +00004782
4783 ArgBuilder operator[]( int position ) {
Phil Nash472dc2a2014-03-17 18:40:58 +00004784 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
4785 if( position > m_highestSpecifiedArgPosition )
4786 m_highestSpecifiedArgPosition = position;
4787 setPositionalArg( m_positionalArgs[position], position );
Phil Nashaf8cd982014-03-24 18:15:04 +00004788 ArgBuilder builder( &m_positionalArgs[position] );
Phil Nashb9fea752014-03-06 08:16:06 +00004789 return builder;
4790 }
4791
4792 // Invoke this with the _ instance
4793 ArgBuilder operator[]( UnpositionalTag ) {
Phil Nash472dc2a2014-03-17 18:40:58 +00004794 if( m_floatingArg.get() )
4795 throw std::logic_error( "Only one unpositional argument can be added" );
Phil Nash85b4e942014-10-02 18:51:05 +01004796 m_floatingArg.reset( new Arg() );
Phil Nashaf8cd982014-03-24 18:15:04 +00004797 ArgBuilder builder( m_floatingArg.get() );
Phil Nashb9fea752014-03-06 08:16:06 +00004798 return builder;
4799 }
4800
Phil Nash472dc2a2014-03-17 18:40:58 +00004801 template<typename C, typename M>
4802 void bindProcessName( M C::* field ) {
4803 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
4804 }
4805 template<typename C, typename M>
4806 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
4807 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
Phil Nash786959d2013-06-07 19:07:50 +01004808 }
4809
Phil Nash1c2fbe12014-02-11 18:12:41 +00004810 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
Phil Nash786959d2013-06-07 19:07:50 +01004811 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4812 std::size_t maxWidth = 0;
4813 for( it = itBegin; it != itEnd; ++it )
4814 maxWidth = (std::max)( maxWidth, it->commands().size() );
4815
4816 for( it = itBegin; it != itEnd; ++it ) {
Phil Nash3b4edd72016-02-10 19:24:48 +00004817 Detail::Text usage( it->commands(), Detail::TextAttributes()
Phil Nash786959d2013-06-07 19:07:50 +01004818 .setWidth( maxWidth+indent )
4819 .setIndent( indent ) );
Phil Nash1c2fbe12014-02-11 18:12:41 +00004820 Detail::Text desc( it->description, Detail::TextAttributes()
Phil Nashaf8cd982014-03-24 18:15:04 +00004821 .setWidth( width - maxWidth - 3 ) );
Phil Nash786959d2013-06-07 19:07:50 +01004822
Phil Nash3b4edd72016-02-10 19:24:48 +00004823 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
4824 std::string usageCol = i < usage.size() ? usage[i] : "";
Phil Nash786959d2013-06-07 19:07:50 +01004825 os << usageCol;
4826
4827 if( i < desc.size() && !desc[i].empty() )
4828 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
4829 << desc[i];
4830 os << "\n";
4831 }
4832 }
4833 }
4834 std::string optUsage() const {
4835 std::ostringstream oss;
4836 optUsage( oss );
4837 return oss.str();
4838 }
4839
4840 void argSynopsis( std::ostream& os ) const {
4841 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4842 if( i > 1 )
4843 os << " ";
4844 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4845 if( it != m_positionalArgs.end() )
Phil Nashb9fea752014-03-06 08:16:06 +00004846 os << "<" << it->second.placeholder << ">";
Phil Nash472dc2a2014-03-17 18:40:58 +00004847 else if( m_floatingArg.get() )
4848 os << "<" << m_floatingArg->placeholder << ">";
Phil Nash786959d2013-06-07 19:07:50 +01004849 else
4850 throw std::logic_error( "non consecutive positional arguments with no floating args" );
4851 }
4852 // !TBD No indication of mandatory args
Phil Nash472dc2a2014-03-17 18:40:58 +00004853 if( m_floatingArg.get() ) {
Phil Nash786959d2013-06-07 19:07:50 +01004854 if( m_highestSpecifiedArgPosition > 1 )
4855 os << " ";
Phil Nash472dc2a2014-03-17 18:40:58 +00004856 os << "[<" << m_floatingArg->placeholder << "> ...]";
Phil Nash786959d2013-06-07 19:07:50 +01004857 }
4858 }
4859 std::string argSynopsis() const {
4860 std::ostringstream oss;
4861 argSynopsis( oss );
4862 return oss.str();
4863 }
4864
4865 void usage( std::ostream& os, std::string const& procName ) const {
Phil Nashaf8cd982014-03-24 18:15:04 +00004866 validate();
Phil Nash786959d2013-06-07 19:07:50 +01004867 os << "usage:\n " << procName << " ";
4868 argSynopsis( os );
4869 if( !m_options.empty() ) {
4870 os << " [options]\n\nwhere options are: \n";
4871 optUsage( os, 2 );
4872 }
4873 os << "\n";
4874 }
4875 std::string usage( std::string const& procName ) const {
4876 std::ostringstream oss;
4877 usage( oss, procName );
4878 return oss.str();
4879 }
4880
Phil Nashe5537842016-04-25 18:56:50 +01004881 ConfigT parse( std::vector<std::string> const& args ) const {
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004882 ConfigT config;
Phil Nashe5537842016-04-25 18:56:50 +01004883 parseInto( args, config );
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004884 return config;
4885 }
4886
Phil Nashe5537842016-04-25 18:56:50 +01004887 std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
4888 std::string processName = args[0];
Phil Nash786959d2013-06-07 19:07:50 +01004889 std::size_t lastSlash = processName.find_last_of( "/\\" );
4890 if( lastSlash != std::string::npos )
4891 processName = processName.substr( lastSlash+1 );
4892 m_boundProcessName.set( config, processName );
4893 std::vector<Parser::Token> tokens;
4894 Parser parser;
Phil Nashe5537842016-04-25 18:56:50 +01004895 parser.parseIntoTokens( args, tokens );
Phil Nash786959d2013-06-07 19:07:50 +01004896 return populate( tokens, config );
4897 }
4898
4899 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
Phil Nashaf8cd982014-03-24 18:15:04 +00004900 validate();
Phil Nash786959d2013-06-07 19:07:50 +01004901 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
4902 unusedTokens = populateFixedArgs( unusedTokens, config );
4903 unusedTokens = populateFloatingArgs( unusedTokens, config );
4904 return unusedTokens;
4905 }
4906
4907 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4908 std::vector<Parser::Token> unusedTokens;
Phil Nash91ef5f72013-12-20 19:06:26 +00004909 std::vector<std::string> errors;
Phil Nash786959d2013-06-07 19:07:50 +01004910 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4911 Parser::Token const& token = tokens[i];
4912 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4913 for(; it != itEnd; ++it ) {
4914 Arg const& arg = *it;
4915
4916 try {
4917 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
4918 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
4919 if( arg.takesArg() ) {
4920 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
Phil Nash91ef5f72013-12-20 19:06:26 +00004921 errors.push_back( "Expected argument to option: " + token.data );
4922 else
4923 arg.boundField.set( config, tokens[++i].data );
Phil Nash786959d2013-06-07 19:07:50 +01004924 }
4925 else {
Phil Nashe5537842016-04-25 18:56:50 +01004926 arg.boundField.set( config, "true" );
Phil Nash786959d2013-06-07 19:07:50 +01004927 }
4928 break;
4929 }
4930 }
4931 catch( std::exception& ex ) {
Phil Nash91ef5f72013-12-20 19:06:26 +00004932 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
Phil Nash786959d2013-06-07 19:07:50 +01004933 }
4934 }
Phil Nash91ef5f72013-12-20 19:06:26 +00004935 if( it == itEnd ) {
4936 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
4937 unusedTokens.push_back( token );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01004938 else if( errors.empty() && m_throwOnUnrecognisedTokens )
Phil Nash91ef5f72013-12-20 19:06:26 +00004939 errors.push_back( "unrecognised option: " + token.data );
4940 }
4941 }
4942 if( !errors.empty() ) {
4943 std::ostringstream oss;
4944 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
4945 it != itEnd;
4946 ++it ) {
4947 if( it != errors.begin() )
4948 oss << "\n";
4949 oss << *it;
4950 }
4951 throw std::runtime_error( oss.str() );
Phil Nash786959d2013-06-07 19:07:50 +01004952 }
4953 return unusedTokens;
4954 }
4955 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4956 std::vector<Parser::Token> unusedTokens;
4957 int position = 1;
4958 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4959 Parser::Token const& token = tokens[i];
4960 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
4961 if( it != m_positionalArgs.end() )
4962 it->second.boundField.set( config, token.data );
4963 else
4964 unusedTokens.push_back( token );
4965 if( token.type == Parser::Token::Positional )
4966 position++;
4967 }
4968 return unusedTokens;
4969 }
4970 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
Phil Nash472dc2a2014-03-17 18:40:58 +00004971 if( !m_floatingArg.get() )
Phil Nash786959d2013-06-07 19:07:50 +01004972 return tokens;
4973 std::vector<Parser::Token> unusedTokens;
4974 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4975 Parser::Token const& token = tokens[i];
4976 if( token.type == Parser::Token::Positional )
Phil Nash472dc2a2014-03-17 18:40:58 +00004977 m_floatingArg->boundField.set( config, token.data );
Phil Nash786959d2013-06-07 19:07:50 +01004978 else
4979 unusedTokens.push_back( token );
4980 }
4981 return unusedTokens;
4982 }
4983
Phil Nashaf8cd982014-03-24 18:15:04 +00004984 void validate() const
4985 {
4986 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
4987 throw std::logic_error( "No options or arguments specified" );
4988
4989 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
4990 itEnd = m_options.end();
4991 it != itEnd; ++it )
4992 it->validate();
4993 }
4994
Phil Nash786959d2013-06-07 19:07:50 +01004995 private:
4996 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
4997 std::vector<Arg> m_options;
4998 std::map<int, Arg> m_positionalArgs;
Phil Nash472dc2a2014-03-17 18:40:58 +00004999 ArgAutoPtr m_floatingArg;
Phil Nash786959d2013-06-07 19:07:50 +01005000 int m_highestSpecifiedArgPosition;
Phil Nash91ef5f72013-12-20 19:06:26 +00005001 bool m_throwOnUnrecognisedTokens;
Phil Nash786959d2013-06-07 19:07:50 +01005002 };
5003
5004} // end namespace Clara
5005
Phil Nashb9fea752014-03-06 08:16:06 +00005006STITCH_CLARA_CLOSE_NAMESPACE
5007#undef STITCH_CLARA_OPEN_NAMESPACE
5008#undef STITCH_CLARA_CLOSE_NAMESPACE
Phil Nash1c2fbe12014-02-11 18:12:41 +00005009
Phil Nash1f1ee3c2014-03-01 10:38:14 +00005010#endif // TWOBLUECUBES_CLARA_H_INCLUDED
Phil Nashb9fea752014-03-06 08:16:06 +00005011#undef STITCH_CLARA_OPEN_NAMESPACE
5012
5013// Restore Clara's value for console width, if present
5014#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5015#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5016#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5017#endif
Phil Nash1c2fbe12014-02-11 18:12:41 +00005018
Phil Nash5ecb72b2013-11-26 20:57:45 +00005019#include <fstream>
Phil Nashd08cee22017-02-13 16:15:42 +00005020#include <ctime>
Phil Nash5ecb72b2013-11-26 20:57:45 +00005021
Phil Nash786959d2013-06-07 19:07:50 +01005022namespace Catch {
5023
5024 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
5025 inline void abortAfterX( ConfigData& config, int x ) {
5026 if( x < 1 )
5027 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
5028 config.abortAfter = x;
5029 }
5030 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005031 inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); }
Phil Nashe73583d2015-08-07 17:30:34 +01005032 inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
Phil Nash786959d2013-06-07 19:07:50 +01005033
5034 inline void addWarning( ConfigData& config, std::string const& _warning ) {
5035 if( _warning == "NoAssertions" )
Phil Nashce562092014-07-09 07:40:37 +01005036 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
Phil Nash786959d2013-06-07 19:07:50 +01005037 else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005038 throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01005039 }
5040 inline void setOrder( ConfigData& config, std::string const& order ) {
5041 if( startsWith( "declared", order ) )
5042 config.runOrder = RunTests::InDeclarationOrder;
5043 else if( startsWith( "lexical", order ) )
5044 config.runOrder = RunTests::InLexicographicalOrder;
5045 else if( startsWith( "random", order ) )
5046 config.runOrder = RunTests::InRandomOrder;
5047 else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005048 throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01005049 }
5050 inline void setRngSeed( ConfigData& config, std::string const& seed ) {
5051 if( seed == "time" ) {
5052 config.rngSeed = static_cast<unsigned int>( std::time(0) );
5053 }
5054 else {
5055 std::stringstream ss;
5056 ss << seed;
5057 ss >> config.rngSeed;
5058 if( ss.fail() )
Phil Nashd08cee22017-02-13 16:15:42 +00005059 throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01005060 }
Phil Nash786959d2013-06-07 19:07:50 +01005061 }
5062 inline void setVerbosity( ConfigData& config, int level ) {
5063 // !TBD: accept strings?
Phil Nashce562092014-07-09 07:40:37 +01005064 config.verbosity = static_cast<Verbosity::Level>( level );
Phil Nashaa7123b2013-08-15 19:01:00 +01005065 }
5066 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
5067 config.showDurations = _showDurations
5068 ? ShowDurations::Always
5069 : ShowDurations::Never;
Phil Nash786959d2013-06-07 19:07:50 +01005070 }
Phil Nashae5ee2c2016-02-29 08:17:18 +00005071 inline void setUseColour( ConfigData& config, std::string const& value ) {
5072 std::string mode = toLower( value );
5073
5074 if( mode == "yes" )
5075 config.useColour = UseColour::Yes;
5076 else if( mode == "no" )
5077 config.useColour = UseColour::No;
5078 else if( mode == "auto" )
5079 config.useColour = UseColour::Auto;
5080 else
5081 throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
5082 }
5083 inline void forceColour( ConfigData& config ) {
5084 config.useColour = UseColour::Yes;
5085 }
Phil Nash5ecb72b2013-11-26 20:57:45 +00005086 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
5087 std::ifstream f( _filename.c_str() );
5088 if( !f.is_open() )
5089 throw std::domain_error( "Unable to load input file: " + _filename );
5090
5091 std::string line;
5092 while( std::getline( f, line ) ) {
5093 line = trim(line);
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005094 if( !line.empty() && !startsWith( line, '#' ) ) {
5095 if( !startsWith( line, '"' ) )
5096 line = '"' + line + '"';
5097 addTestOrTags( config, line + ',' );
Phil Nash40f60682016-09-27 10:46:22 +01005098 }
Phil Nash5ecb72b2013-11-26 20:57:45 +00005099 }
5100 }
Phil Nash786959d2013-06-07 19:07:50 +01005101
5102 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
5103
Phil Nashb9fea752014-03-06 08:16:06 +00005104 using namespace Clara;
5105 CommandLine<ConfigData> cli;
Phil Nash786959d2013-06-07 19:07:50 +01005106
5107 cli.bindProcessName( &ConfigData::processName );
5108
Phil Nashb9fea752014-03-06 08:16:06 +00005109 cli["-?"]["-h"]["--help"]
Phil Nash786959d2013-06-07 19:07:50 +01005110 .describe( "display usage information" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005111 .bind( &ConfigData::showHelp );
Phil Nash786959d2013-06-07 19:07:50 +01005112
Phil Nashb9fea752014-03-06 08:16:06 +00005113 cli["-l"]["--list-tests"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005114 .describe( "list all/matching test cases" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005115 .bind( &ConfigData::listTests );
Phil Nash786959d2013-06-07 19:07:50 +01005116
Phil Nashb9fea752014-03-06 08:16:06 +00005117 cli["-t"]["--list-tags"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005118 .describe( "list all/matching tags" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005119 .bind( &ConfigData::listTags );
Phil Nash786959d2013-06-07 19:07:50 +01005120
Phil Nashb9fea752014-03-06 08:16:06 +00005121 cli["-s"]["--success"]
Phil Nash786959d2013-06-07 19:07:50 +01005122 .describe( "include successful tests in output" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005123 .bind( &ConfigData::showSuccessfulTests );
Phil Nash786959d2013-06-07 19:07:50 +01005124
Phil Nashb9fea752014-03-06 08:16:06 +00005125 cli["-b"]["--break"]
Phil Nash786959d2013-06-07 19:07:50 +01005126 .describe( "break into debugger on failure" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005127 .bind( &ConfigData::shouldDebugBreak );
Phil Nash786959d2013-06-07 19:07:50 +01005128
Phil Nashb9fea752014-03-06 08:16:06 +00005129 cli["-e"]["--nothrow"]
Phil Nash7d5f2712013-06-07 21:15:25 +01005130 .describe( "skip exception tests" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005131 .bind( &ConfigData::noThrow );
Phil Nash786959d2013-06-07 19:07:50 +01005132
Phil Nashaef6cd52014-04-23 07:10:10 +01005133 cli["-i"]["--invisibles"]
5134 .describe( "show invisibles (tabs, newlines)" )
5135 .bind( &ConfigData::showInvisibles );
5136
Phil Nashb9fea752014-03-06 08:16:06 +00005137 cli["-o"]["--out"]
Phil Nash786959d2013-06-07 19:07:50 +01005138 .describe( "output filename" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005139 .bind( &ConfigData::outputFilename, "filename" );
Phil Nash786959d2013-06-07 19:07:50 +01005140
Phil Nashb9fea752014-03-06 08:16:06 +00005141 cli["-r"]["--reporter"]
5142// .placeholder( "name[:filename]" )
Phil Nash5ecb72b2013-11-26 20:57:45 +00005143 .describe( "reporter to use (defaults to console)" )
Phil Nashe73583d2015-08-07 17:30:34 +01005144 .bind( &addReporterName, "name" );
Phil Nash786959d2013-06-07 19:07:50 +01005145
Phil Nashb9fea752014-03-06 08:16:06 +00005146 cli["-n"]["--name"]
Phil Nash786959d2013-06-07 19:07:50 +01005147 .describe( "suite name" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005148 .bind( &ConfigData::name, "name" );
Phil Nash786959d2013-06-07 19:07:50 +01005149
Phil Nashb9fea752014-03-06 08:16:06 +00005150 cli["-a"]["--abort"]
Phil Nash786959d2013-06-07 19:07:50 +01005151 .describe( "abort at first failure" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005152 .bind( &abortAfterFirst );
Phil Nash786959d2013-06-07 19:07:50 +01005153
Phil Nashb9fea752014-03-06 08:16:06 +00005154 cli["-x"]["--abortx"]
Phil Nash786959d2013-06-07 19:07:50 +01005155 .describe( "abort after x failures" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005156 .bind( &abortAfterX, "no. failures" );
Phil Nash786959d2013-06-07 19:07:50 +01005157
Phil Nashb9fea752014-03-06 08:16:06 +00005158 cli["-w"]["--warn"]
Phil Nash786959d2013-06-07 19:07:50 +01005159 .describe( "enable warnings" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005160 .bind( &addWarning, "warning name" );
Phil Nash786959d2013-06-07 19:07:50 +01005161
Phil Nashb9fea752014-03-06 08:16:06 +00005162// - needs updating if reinstated
5163// cli.into( &setVerbosity )
Phil Nash786959d2013-06-07 19:07:50 +01005164// .describe( "level of verbosity (0=no output)" )
5165// .shortOpt( "v")
5166// .longOpt( "verbosity" )
Phil Nashb9fea752014-03-06 08:16:06 +00005167// .placeholder( "level" );
Phil Nash786959d2013-06-07 19:07:50 +01005168
Phil Nashb9fea752014-03-06 08:16:06 +00005169 cli[_]
Phil Nash786959d2013-06-07 19:07:50 +01005170 .describe( "which test or tests to use" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005171 .bind( &addTestOrTags, "test name, pattern or tags" );
Phil Nash786959d2013-06-07 19:07:50 +01005172
Phil Nashb9fea752014-03-06 08:16:06 +00005173 cli["-d"]["--durations"]
Phil Nashaa7123b2013-08-15 19:01:00 +01005174 .describe( "show test durations" )
Phil Nashae5ee2c2016-02-29 08:17:18 +00005175 .bind( &setShowDurations, "yes|no" );
Phil Nashaa7123b2013-08-15 19:01:00 +01005176
Phil Nashb9fea752014-03-06 08:16:06 +00005177 cli["-f"]["--input-file"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005178 .describe( "load test names to run from a file" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005179 .bind( &loadTestNamesFromFile, "filename" );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005180
Phil Nashe6b365d2015-07-07 08:25:15 +01005181 cli["-#"]["--filenames-as-tags"]
5182 .describe( "adds a tag for the filename" )
5183 .bind( &ConfigData::filenamesAsTags );
5184
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005185 cli["-c"]["--section"]
5186 .describe( "specify section to run" )
5187 .bind( &addSectionToRun, "section name" );
5188
Phil Nash5ecb72b2013-11-26 20:57:45 +00005189 // Less common commands which don't have a short form
Phil Nashb9fea752014-03-06 08:16:06 +00005190 cli["--list-test-names-only"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005191 .describe( "list all/matching test cases names only" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005192 .bind( &ConfigData::listTestNamesOnly );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005193
Phil Nashb9fea752014-03-06 08:16:06 +00005194 cli["--list-reporters"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005195 .describe( "list all reporters" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005196 .bind( &ConfigData::listReporters );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005197
Phil Nash6a8e8ad2014-09-15 18:40:24 +01005198 cli["--order"]
5199 .describe( "test case order (defaults to decl)" )
5200 .bind( &setOrder, "decl|lex|rand" );
5201
5202 cli["--rng-seed"]
5203 .describe( "set a specific seed for random numbers" )
5204 .bind( &setRngSeed, "'time'|number" );
5205
Phil Nasha806c3e2015-03-04 08:23:40 +00005206 cli["--force-colour"]
Phil Nashae5ee2c2016-02-29 08:17:18 +00005207 .describe( "force colourised output (deprecated)" )
5208 .bind( &forceColour );
5209
5210 cli["--use-colour"]
5211 .describe( "should output be colourised" )
5212 .bind( &setUseColour, "yes|no" );
Phil Nasha806c3e2015-03-04 08:23:40 +00005213
Phil Nash786959d2013-06-07 19:07:50 +01005214 return cli;
5215 }
5216
Phil Nasha695eb92012-08-13 07:46:10 +01005217} // end namespace Catch
5218
5219// #included from: internal/catch_list.hpp
5220#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
5221
Phil Nash1c2fbe12014-02-11 18:12:41 +00005222// #included from: catch_text.h
5223#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
5224
5225#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
5226
5227#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
Phil Nash472dc2a2014-03-17 18:40:58 +00005228// #included from: ../external/tbc_text_format.h
Phil Nash1c2fbe12014-02-11 18:12:41 +00005229// Only use header guard if we are not using an outer namespace
5230#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5231# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5232# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5233# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5234# endif
5235# else
5236# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5237# endif
5238#endif
5239#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5240#include <string>
5241#include <vector>
5242#include <sstream>
5243
5244// Use optional outer namespace
5245#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5246namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
5247#endif
5248
5249namespace Tbc {
5250
5251#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
5252 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
5253#else
5254 const unsigned int consoleWidth = 80;
5255#endif
5256
5257 struct TextAttributes {
5258 TextAttributes()
5259 : initialIndent( std::string::npos ),
5260 indent( 0 ),
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005261 width( consoleWidth-1 )
Phil Nash1c2fbe12014-02-11 18:12:41 +00005262 {}
5263
5264 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
5265 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
5266 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
Phil Nash1c2fbe12014-02-11 18:12:41 +00005267
5268 std::size_t initialIndent; // indent of first line, or npos
5269 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
5270 std::size_t width; // maximum width of text, including indent. Longer text will wrap
Phil Nash1c2fbe12014-02-11 18:12:41 +00005271 };
5272
5273 class Text {
5274 public:
5275 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
5276 : attr( _attr )
5277 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005278 const std::string wrappableBeforeChars = "[({<\t";
5279 const std::string wrappableAfterChars = "])}>-,./|\\";
5280 const std::string wrappableInsteadOfChars = " \n\r";
5281 std::string indent = _attr.initialIndent != std::string::npos
5282 ? std::string( _attr.initialIndent, ' ' )
5283 : std::string( _attr.indent, ' ' );
Phil Nash1c2fbe12014-02-11 18:12:41 +00005284
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005285 typedef std::string::const_iterator iterator;
5286 iterator it = _str.begin();
5287 const iterator strEnd = _str.end();
5288
5289 while( it != strEnd ) {
5290
Phil Nash1c2fbe12014-02-11 18:12:41 +00005291 if( lines.size() >= 1000 ) {
5292 lines.push_back( "... message truncated due to excessive size" );
5293 return;
5294 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00005295
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005296 std::string suffix;
5297 std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
5298 iterator itEnd = it+width;
5299 iterator itNext = _str.end();
5300
5301 iterator itNewLine = std::find( it, itEnd, '\n' );
5302 if( itNewLine != itEnd )
5303 itEnd = itNewLine;
5304
5305 if( itEnd != strEnd ) {
5306 bool foundWrapPoint = false;
5307 iterator findIt = itEnd;
5308 do {
5309 if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) {
5310 itEnd = findIt+1;
5311 itNext = findIt+1;
5312 foundWrapPoint = true;
5313 }
5314 else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) {
5315 itEnd = findIt;
5316 itNext = findIt;
5317 foundWrapPoint = true;
5318 }
5319 else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) {
5320 itNext = findIt+1;
5321 itEnd = findIt;
5322 foundWrapPoint = true;
5323 }
5324 if( findIt == it )
5325 break;
5326 else
5327 --findIt;
5328 }
5329 while( !foundWrapPoint );
5330
5331 if( !foundWrapPoint ) {
5332 // No good wrap char, so we'll break mid word and add a hyphen
5333 --itEnd;
5334 itNext = itEnd;
5335 suffix = "-";
Phil Nash1c2fbe12014-02-11 18:12:41 +00005336 }
5337 else {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005338 while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos )
5339 --itEnd;
Phil Nash1c2fbe12014-02-11 18:12:41 +00005340 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00005341 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005342 lines.push_back( indent + std::string( it, itEnd ) + suffix );
Phil Nash1c2fbe12014-02-11 18:12:41 +00005343
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005344 if( indent.size() != _attr.indent )
5345 indent = std::string( _attr.indent, ' ' );
5346 it = itNext;
5347 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00005348 }
5349
5350 typedef std::vector<std::string>::const_iterator const_iterator;
5351
5352 const_iterator begin() const { return lines.begin(); }
5353 const_iterator end() const { return lines.end(); }
5354 std::string const& last() const { return lines.back(); }
5355 std::size_t size() const { return lines.size(); }
5356 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
5357 std::string toString() const {
5358 std::ostringstream oss;
5359 oss << *this;
5360 return oss.str();
5361 }
5362
5363 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
5364 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
5365 it != itEnd; ++it ) {
5366 if( it != _text.begin() )
5367 _stream << "\n";
5368 _stream << *it;
5369 }
5370 return _stream;
5371 }
5372
5373 private:
5374 std::string str;
5375 TextAttributes attr;
5376 std::vector<std::string> lines;
5377 };
5378
5379} // end namespace Tbc
5380
5381#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5382} // end outer namespace
5383#endif
5384
5385#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5386#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5387
5388namespace Catch {
5389 using Tbc::Text;
5390 using Tbc::TextAttributes;
5391}
5392
Phil Nash5c7d3d72013-04-01 11:27:10 +01005393// #included from: catch_console_colour.hpp
5394#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01005395
5396namespace Catch {
Phil Nash5c7d3d72013-04-01 11:27:10 +01005397
Phil Nash12c16ff2013-04-05 20:58:01 +01005398 struct Colour {
5399 enum Code {
5400 None = 0,
Phil Nash5c7d3d72013-04-01 11:27:10 +01005401
Phil Nash12c16ff2013-04-05 20:58:01 +01005402 White,
5403 Red,
5404 Green,
5405 Blue,
5406 Cyan,
5407 Yellow,
5408 Grey,
Phil Nash5c7d3d72013-04-01 11:27:10 +01005409
Phil Nash12c16ff2013-04-05 20:58:01 +01005410 Bright = 0x10,
Phil Nash5c7d3d72013-04-01 11:27:10 +01005411
Phil Nash12c16ff2013-04-05 20:58:01 +01005412 BrightRed = Bright | Red,
5413 BrightGreen = Bright | Green,
5414 LightGrey = Bright | Grey,
5415 BrightWhite = Bright | White,
5416
5417 // By intention
5418 FileName = LightGrey,
Phil Nash52e1e742014-07-03 08:11:38 +01005419 Warning = Yellow,
Phil Nash12c16ff2013-04-05 20:58:01 +01005420 ResultError = BrightRed,
5421 ResultSuccess = BrightGreen,
Phil Nash52e1e742014-07-03 08:11:38 +01005422 ResultExpectedFailure = Warning,
Phil Nash12c16ff2013-04-05 20:58:01 +01005423
5424 Error = BrightRed,
5425 Success = Green,
5426
5427 OriginalExpression = Cyan,
5428 ReconstructedExpression = Yellow,
5429
5430 SecondaryText = LightGrey,
5431 Headers = White
Phil Nash5c7d3d72013-04-01 11:27:10 +01005432 };
5433
Phil Nash12c16ff2013-04-05 20:58:01 +01005434 // Use constructed object for RAII guard
5435 Colour( Code _colourCode );
Phil Nashce562092014-07-09 07:40:37 +01005436 Colour( Colour const& other );
Phil Nash12c16ff2013-04-05 20:58:01 +01005437 ~Colour();
Phil Nash5c7d3d72013-04-01 11:27:10 +01005438
Phil Nash12c16ff2013-04-05 20:58:01 +01005439 // Use static method for one-shot changes
5440 static void use( Code _colourCode );
Phil Nash5c7d3d72013-04-01 11:27:10 +01005441
5442 private:
Phil Nashce562092014-07-09 07:40:37 +01005443 bool m_moved;
Phil Nash5c7d3d72013-04-01 11:27:10 +01005444 };
5445
Phil Nash52e1e742014-07-03 08:11:38 +01005446 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
5447
Phil Nash5c7d3d72013-04-01 11:27:10 +01005448} // end namespace Catch
5449
Phil Nash3649fdf2013-12-03 18:53:55 +00005450// #included from: catch_interfaces_reporter.h
5451#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
5452
Phil Nash3649fdf2013-12-03 18:53:55 +00005453#include <string>
5454#include <ostream>
5455#include <map>
Phil Nash3649fdf2013-12-03 18:53:55 +00005456
5457namespace Catch
5458{
5459 struct ReporterConfig {
Phil Nash7e346192015-11-03 08:00:43 +00005460 explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
Phil Nash3649fdf2013-12-03 18:53:55 +00005461 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
5462
Phil Nash7e346192015-11-03 08:00:43 +00005463 ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
Phil Nash3649fdf2013-12-03 18:53:55 +00005464 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
5465
5466 std::ostream& stream() const { return *m_stream; }
Phil Nash7e346192015-11-03 08:00:43 +00005467 Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
Phil Nash3649fdf2013-12-03 18:53:55 +00005468
5469 private:
5470 std::ostream* m_stream;
Phil Nash7e346192015-11-03 08:00:43 +00005471 Ptr<IConfig const> m_fullConfig;
Phil Nash3649fdf2013-12-03 18:53:55 +00005472 };
5473
5474 struct ReporterPreferences {
5475 ReporterPreferences()
5476 : shouldRedirectStdOut( false )
5477 {}
5478
5479 bool shouldRedirectStdOut;
5480 };
5481
5482 template<typename T>
5483 struct LazyStat : Option<T> {
5484 LazyStat() : used( false ) {}
5485 LazyStat& operator=( T const& _value ) {
5486 Option<T>::operator=( _value );
5487 used = false;
5488 return *this;
5489 }
5490 void reset() {
5491 Option<T>::reset();
5492 used = false;
5493 }
5494 bool used;
5495 };
5496
5497 struct TestRunInfo {
5498 TestRunInfo( std::string const& _name ) : name( _name ) {}
5499 std::string name;
5500 };
5501 struct GroupInfo {
5502 GroupInfo( std::string const& _name,
5503 std::size_t _groupIndex,
5504 std::size_t _groupsCount )
5505 : name( _name ),
5506 groupIndex( _groupIndex ),
5507 groupsCounts( _groupsCount )
5508 {}
5509
5510 std::string name;
5511 std::size_t groupIndex;
5512 std::size_t groupsCounts;
5513 };
5514
5515 struct AssertionStats {
5516 AssertionStats( AssertionResult const& _assertionResult,
5517 std::vector<MessageInfo> const& _infoMessages,
5518 Totals const& _totals )
5519 : assertionResult( _assertionResult ),
5520 infoMessages( _infoMessages ),
5521 totals( _totals )
5522 {
5523 if( assertionResult.hasMessage() ) {
5524 // Copy message into messages list.
5525 // !TBD This should have been done earlier, somewhere
5526 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
5527 builder << assertionResult.getMessage();
5528 builder.m_info.message = builder.m_stream.str();
5529
5530 infoMessages.push_back( builder.m_info );
5531 }
5532 }
5533 virtual ~AssertionStats();
5534
Phil Nash318c9362015-05-19 18:40:00 +01005535# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005536 AssertionStats( AssertionStats const& ) = default;
5537 AssertionStats( AssertionStats && ) = default;
5538 AssertionStats& operator = ( AssertionStats const& ) = default;
5539 AssertionStats& operator = ( AssertionStats && ) = default;
5540# endif
5541
Phil Nash3649fdf2013-12-03 18:53:55 +00005542 AssertionResult assertionResult;
5543 std::vector<MessageInfo> infoMessages;
5544 Totals totals;
5545 };
5546
5547 struct SectionStats {
5548 SectionStats( SectionInfo const& _sectionInfo,
5549 Counts const& _assertions,
5550 double _durationInSeconds,
5551 bool _missingAssertions )
5552 : sectionInfo( _sectionInfo ),
5553 assertions( _assertions ),
5554 durationInSeconds( _durationInSeconds ),
5555 missingAssertions( _missingAssertions )
5556 {}
5557 virtual ~SectionStats();
Phil Nash318c9362015-05-19 18:40:00 +01005558# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005559 SectionStats( SectionStats const& ) = default;
5560 SectionStats( SectionStats && ) = default;
5561 SectionStats& operator = ( SectionStats const& ) = default;
5562 SectionStats& operator = ( SectionStats && ) = default;
5563# endif
Phil Nash3649fdf2013-12-03 18:53:55 +00005564
5565 SectionInfo sectionInfo;
5566 Counts assertions;
5567 double durationInSeconds;
5568 bool missingAssertions;
5569 };
5570
5571 struct TestCaseStats {
5572 TestCaseStats( TestCaseInfo const& _testInfo,
5573 Totals const& _totals,
5574 std::string const& _stdOut,
5575 std::string const& _stdErr,
5576 bool _aborting )
5577 : testInfo( _testInfo ),
5578 totals( _totals ),
5579 stdOut( _stdOut ),
5580 stdErr( _stdErr ),
5581 aborting( _aborting )
5582 {}
5583 virtual ~TestCaseStats();
5584
Phil Nash318c9362015-05-19 18:40:00 +01005585# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005586 TestCaseStats( TestCaseStats const& ) = default;
5587 TestCaseStats( TestCaseStats && ) = default;
5588 TestCaseStats& operator = ( TestCaseStats const& ) = default;
5589 TestCaseStats& operator = ( TestCaseStats && ) = default;
5590# endif
5591
Phil Nash3649fdf2013-12-03 18:53:55 +00005592 TestCaseInfo testInfo;
5593 Totals totals;
5594 std::string stdOut;
5595 std::string stdErr;
5596 bool aborting;
5597 };
5598
5599 struct TestGroupStats {
5600 TestGroupStats( GroupInfo const& _groupInfo,
5601 Totals const& _totals,
5602 bool _aborting )
5603 : groupInfo( _groupInfo ),
5604 totals( _totals ),
5605 aborting( _aborting )
5606 {}
5607 TestGroupStats( GroupInfo const& _groupInfo )
5608 : groupInfo( _groupInfo ),
5609 aborting( false )
5610 {}
5611 virtual ~TestGroupStats();
5612
Phil Nash318c9362015-05-19 18:40:00 +01005613# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005614 TestGroupStats( TestGroupStats const& ) = default;
5615 TestGroupStats( TestGroupStats && ) = default;
5616 TestGroupStats& operator = ( TestGroupStats const& ) = default;
5617 TestGroupStats& operator = ( TestGroupStats && ) = default;
5618# endif
5619
Phil Nash3649fdf2013-12-03 18:53:55 +00005620 GroupInfo groupInfo;
5621 Totals totals;
5622 bool aborting;
5623 };
5624
5625 struct TestRunStats {
5626 TestRunStats( TestRunInfo const& _runInfo,
5627 Totals const& _totals,
5628 bool _aborting )
5629 : runInfo( _runInfo ),
5630 totals( _totals ),
5631 aborting( _aborting )
5632 {}
Phil Nashd7e17902014-04-18 08:49:35 +01005633 virtual ~TestRunStats();
5634
Phil Nash318c9362015-05-19 18:40:00 +01005635# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nash3649fdf2013-12-03 18:53:55 +00005636 TestRunStats( TestRunStats const& _other )
5637 : runInfo( _other.runInfo ),
5638 totals( _other.totals ),
5639 aborting( _other.aborting )
5640 {}
Phil Nashd7e17902014-04-18 08:49:35 +01005641# else
5642 TestRunStats( TestRunStats const& ) = default;
5643 TestRunStats( TestRunStats && ) = default;
5644 TestRunStats& operator = ( TestRunStats const& ) = default;
5645 TestRunStats& operator = ( TestRunStats && ) = default;
5646# endif
Phil Nash3649fdf2013-12-03 18:53:55 +00005647
5648 TestRunInfo runInfo;
5649 Totals totals;
5650 bool aborting;
5651 };
5652
Phil Nash92b141e2016-04-28 08:13:00 +01005653 class MultipleReporters;
5654
Phil Nash3649fdf2013-12-03 18:53:55 +00005655 struct IStreamingReporter : IShared {
5656 virtual ~IStreamingReporter();
5657
5658 // Implementing class must also provide the following static method:
5659 // static std::string getDescription();
5660
5661 virtual ReporterPreferences getPreferences() const = 0;
5662
5663 virtual void noMatchingTestCases( std::string const& spec ) = 0;
5664
5665 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
5666 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
5667
5668 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
5669 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
5670
5671 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
5672
Phil Nash576aff62014-12-21 00:21:23 +00005673 // The return value indicates if the messages buffer should be cleared:
Phil Nash3649fdf2013-12-03 18:53:55 +00005674 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
Phil Nashe73583d2015-08-07 17:30:34 +01005675
Phil Nash3649fdf2013-12-03 18:53:55 +00005676 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
5677 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
5678 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
5679 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
Phil Nash92f08362014-12-22 20:18:05 +00005680
5681 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
Phil Nash92b141e2016-04-28 08:13:00 +01005682
5683 virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
Phil Nash3649fdf2013-12-03 18:53:55 +00005684 };
5685
Phil Nashe73583d2015-08-07 17:30:34 +01005686 struct IReporterFactory : IShared {
Phil Nash3649fdf2013-12-03 18:53:55 +00005687 virtual ~IReporterFactory();
5688 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
5689 virtual std::string getDescription() const = 0;
5690 };
5691
5692 struct IReporterRegistry {
Phil Nashe73583d2015-08-07 17:30:34 +01005693 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
5694 typedef std::vector<Ptr<IReporterFactory> > Listeners;
Phil Nash3649fdf2013-12-03 18:53:55 +00005695
5696 virtual ~IReporterRegistry();
Phil Nash7e346192015-11-03 08:00:43 +00005697 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00005698 virtual FactoryMap const& getFactories() const = 0;
Phil Nashe73583d2015-08-07 17:30:34 +01005699 virtual Listeners const& getListeners() const = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00005700 };
5701
Phil Nashe73583d2015-08-07 17:30:34 +01005702 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
5703
Phil Nash3649fdf2013-12-03 18:53:55 +00005704}
5705
Phil Nasha695eb92012-08-13 07:46:10 +01005706#include <limits>
Phil Nash38f7eef2013-03-29 13:44:33 +00005707#include <algorithm>
Phil Nasha695eb92012-08-13 07:46:10 +01005708
5709namespace Catch {
Phil Nasha695eb92012-08-13 07:46:10 +01005710
Phil Nash786959d2013-06-07 19:07:50 +01005711 inline std::size_t listTests( Config const& config ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01005712
5713 TestSpec testSpec = config.testSpec();
5714 if( config.testSpec().hasFilters() )
Phil Nash383d7c02014-10-02 19:08:19 +01005715 Catch::cout() << "Matching test cases:\n";
Phil Nash65cc14c2014-05-16 18:54:48 +01005716 else {
Phil Nash383d7c02014-10-02 19:08:19 +01005717 Catch::cout() << "All available test cases:\n";
Phil Nashacdd3b52014-06-30 07:35:36 +01005718 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
Phil Nash65cc14c2014-05-16 18:54:48 +01005719 }
Phil Nash38f7eef2013-03-29 13:44:33 +00005720
5721 std::size_t matchedTests = 0;
Phil Nash8d44f2d2013-11-13 08:10:45 +00005722 TextAttributes nameAttr, tagsAttr;
5723 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
5724 tagsAttr.setIndent( 6 );
5725
Phil Nashe73583d2015-08-07 17:30:34 +01005726 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
Phil Nash20cad7c2014-04-15 18:44:37 +01005727 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
Phil Nash8d44f2d2013-11-13 08:10:45 +00005728 it != itEnd;
Phil Nash20cad7c2014-04-15 18:44:37 +01005729 ++it ) {
5730 matchedTests++;
5731 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
Phil Nash52e1e742014-07-03 08:11:38 +01005732 Colour::Code colour = testCaseInfo.isHidden()
Phil Nash20cad7c2014-04-15 18:44:37 +01005733 ? Colour::SecondaryText
5734 : Colour::None;
5735 Colour colourGuard( colour );
Phil Nash38f7eef2013-03-29 13:44:33 +00005736
Phil Nash383d7c02014-10-02 19:08:19 +01005737 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
Phil Nash20cad7c2014-04-15 18:44:37 +01005738 if( !testCaseInfo.tags.empty() )
Phil Nash383d7c02014-10-02 19:08:19 +01005739 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
Phil Nash20cad7c2014-04-15 18:44:37 +01005740 }
Phil Nash8d44f2d2013-11-13 08:10:45 +00005741
Phil Nash65cc14c2014-05-16 18:54:48 +01005742 if( !config.testSpec().hasFilters() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005743 Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl;
Phil Nash38f7eef2013-03-29 13:44:33 +00005744 else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005745 Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01005746 return matchedTests;
Phil Nash38f7eef2013-03-29 13:44:33 +00005747 }
Phil Nasha695eb92012-08-13 07:46:10 +01005748
Phil Nash5ecb72b2013-11-26 20:57:45 +00005749 inline std::size_t listTestsNamesOnly( Config const& config ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01005750 TestSpec testSpec = config.testSpec();
5751 if( !config.testSpec().hasFilters() )
Phil Nashacdd3b52014-06-30 07:35:36 +01005752 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
Phil Nash5ecb72b2013-11-26 20:57:45 +00005753 std::size_t matchedTests = 0;
Phil Nashe73583d2015-08-07 17:30:34 +01005754 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
Phil Nash20cad7c2014-04-15 18:44:37 +01005755 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
Phil Nash5ecb72b2013-11-26 20:57:45 +00005756 it != itEnd;
Phil Nash20cad7c2014-04-15 18:44:37 +01005757 ++it ) {
5758 matchedTests++;
5759 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005760 if( startsWith( testCaseInfo.name, '#' ) )
5761 Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl;
Phil Nash40f60682016-09-27 10:46:22 +01005762 else
5763 Catch::cout() << testCaseInfo.name << std::endl;
Phil Nash20cad7c2014-04-15 18:44:37 +01005764 }
Phil Nash5ecb72b2013-11-26 20:57:45 +00005765 return matchedTests;
5766 }
5767
Phil Nash48fac9c2014-05-20 19:02:37 +01005768 struct TagInfo {
5769 TagInfo() : count ( 0 ) {}
5770 void add( std::string const& spelling ) {
5771 ++count;
5772 spellings.insert( spelling );
5773 }
5774 std::string all() const {
5775 std::string out;
5776 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5777 it != itEnd;
5778 ++it )
5779 out += "[" + *it + "]";
5780 return out;
5781 }
5782 std::set<std::string> spellings;
5783 std::size_t count;
5784 };
5785
Phil Nash786959d2013-06-07 19:07:50 +01005786 inline std::size_t listTags( Config const& config ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01005787 TestSpec testSpec = config.testSpec();
5788 if( config.testSpec().hasFilters() )
Phil Nash383d7c02014-10-02 19:08:19 +01005789 Catch::cout() << "Tags for matching test cases:\n";
Phil Nash65cc14c2014-05-16 18:54:48 +01005790 else {
Phil Nash383d7c02014-10-02 19:08:19 +01005791 Catch::cout() << "All available tags:\n";
Phil Nashacdd3b52014-06-30 07:35:36 +01005792 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
Phil Nash65cc14c2014-05-16 18:54:48 +01005793 }
Phil Nash38f7eef2013-03-29 13:44:33 +00005794
Phil Nash9241e432014-05-20 18:50:59 +01005795 std::map<std::string, TagInfo> tagCounts;
Phil Nash38f7eef2013-03-29 13:44:33 +00005796
Phil Nashe73583d2015-08-07 17:30:34 +01005797 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
Phil Nash20cad7c2014-04-15 18:44:37 +01005798 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
Phil Nash8d44f2d2013-11-13 08:10:45 +00005799 it != itEnd;
5800 ++it ) {
Phil Nash20cad7c2014-04-15 18:44:37 +01005801 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5802 tagItEnd = it->getTestCaseInfo().tags.end();
5803 tagIt != tagItEnd;
5804 ++tagIt ) {
5805 std::string tagName = *tagIt;
Phil Nash9241e432014-05-20 18:50:59 +01005806 std::string lcaseTagName = toLower( tagName );
5807 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
Phil Nash20cad7c2014-04-15 18:44:37 +01005808 if( countIt == tagCounts.end() )
Phil Nash9241e432014-05-20 18:50:59 +01005809 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
5810 countIt->second.add( tagName );
Phil Nash38f7eef2013-03-29 13:44:33 +00005811 }
Phil Nasha695eb92012-08-13 07:46:10 +01005812 }
Phil Nash38f7eef2013-03-29 13:44:33 +00005813
Phil Nash9241e432014-05-20 18:50:59 +01005814 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5815 countItEnd = tagCounts.end();
Phil Nash38f7eef2013-03-29 13:44:33 +00005816 countIt != countItEnd;
5817 ++countIt ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +00005818 std::ostringstream oss;
Phil Nash9241e432014-05-20 18:50:59 +01005819 oss << " " << std::setw(2) << countIt->second.count << " ";
5820 Text wrapper( countIt->second.all(), TextAttributes()
5821 .setInitialIndent( 0 )
5822 .setIndent( oss.str().size() )
5823 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005824 Catch::cout() << oss.str() << wrapper << '\n';
Phil Nash38f7eef2013-03-29 13:44:33 +00005825 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005826 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01005827 return tagCounts.size();
Phil Nash38f7eef2013-03-29 13:44:33 +00005828 }
5829
Phil Nash786959d2013-06-07 19:07:50 +01005830 inline std::size_t listReporters( Config const& /*config*/ ) {
Phil Nash576aff62014-12-21 00:21:23 +00005831 Catch::cout() << "Available reporters:\n";
Phil Nash38f7eef2013-03-29 13:44:33 +00005832 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
Phil Nash786959d2013-06-07 19:07:50 +01005833 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
5834 std::size_t maxNameLen = 0;
5835 for(it = itBegin; it != itEnd; ++it )
5836 maxNameLen = (std::max)( maxNameLen, it->first.size() );
5837
5838 for(it = itBegin; it != itEnd; ++it ) {
5839 Text wrapper( it->second->getDescription(), TextAttributes()
5840 .setInitialIndent( 0 )
5841 .setIndent( 7+maxNameLen )
5842 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
Phil Nash383d7c02014-10-02 19:08:19 +01005843 Catch::cout() << " "
Phil Nash786959d2013-06-07 19:07:50 +01005844 << it->first
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005845 << ':'
Phil Nash786959d2013-06-07 19:07:50 +01005846 << std::string( maxNameLen - it->first.size() + 2, ' ' )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005847 << wrapper << '\n';
Phil Nash38f7eef2013-03-29 13:44:33 +00005848 }
Phil Nash383d7c02014-10-02 19:08:19 +01005849 Catch::cout() << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01005850 return factories.size();
Phil Nash38f7eef2013-03-29 13:44:33 +00005851 }
5852
Phil Nash786959d2013-06-07 19:07:50 +01005853 inline Option<std::size_t> list( Config const& config ) {
5854 Option<std::size_t> listedCount;
5855 if( config.listTests() )
5856 listedCount = listedCount.valueOr(0) + listTests( config );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005857 if( config.listTestNamesOnly() )
5858 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
Phil Nash786959d2013-06-07 19:07:50 +01005859 if( config.listTags() )
5860 listedCount = listedCount.valueOr(0) + listTags( config );
5861 if( config.listReporters() )
5862 listedCount = listedCount.valueOr(0) + listReporters( config );
5863 return listedCount;
Phil Nasha695eb92012-08-13 07:46:10 +01005864 }
5865
5866} // end namespace Catch
5867
Phil Nashe73583d2015-08-07 17:30:34 +01005868// #included from: internal/catch_run_context.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005869#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01005870
Phil Nash8a52a392013-07-25 08:12:03 +01005871// #included from: catch_test_case_tracker.hpp
5872#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01005873
5874#include <map>
5875#include <string>
Phil Nash8a52a392013-07-25 08:12:03 +01005876#include <assert.h>
Phil Nash7e346192015-11-03 08:00:43 +00005877#include <vector>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005878#include <iterator>
Phil Nashd08cee22017-02-13 16:15:42 +00005879#include <stdexcept>
Phil Nasha695eb92012-08-13 07:46:10 +01005880
5881namespace Catch {
Phil Nash7e346192015-11-03 08:00:43 +00005882namespace TestCaseTracking {
Phil Nasha695eb92012-08-13 07:46:10 +01005883
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005884 struct NameAndLocation {
5885 std::string name;
5886 SourceLineInfo location;
5887
5888 NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
5889 : name( _name ),
5890 location( _location )
5891 {}
5892 };
5893
Phil Nash7e346192015-11-03 08:00:43 +00005894 struct ITracker : SharedImpl<> {
5895 virtual ~ITracker();
Phil Nash8a52a392013-07-25 08:12:03 +01005896
Phil Nash7e346192015-11-03 08:00:43 +00005897 // static queries
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005898 virtual NameAndLocation const& nameAndLocation() const = 0;
Phil Nash8a52a392013-07-25 08:12:03 +01005899
Phil Nash7e346192015-11-03 08:00:43 +00005900 // dynamic queries
5901 virtual bool isComplete() const = 0; // Successfully completed or failed
5902 virtual bool isSuccessfullyCompleted() const = 0;
5903 virtual bool isOpen() const = 0; // Started but not complete
5904 virtual bool hasChildren() const = 0;
5905
5906 virtual ITracker& parent() = 0;
5907
5908 // actions
5909 virtual void close() = 0; // Successfully complete
5910 virtual void fail() = 0;
5911 virtual void markAsNeedingAnotherRun() = 0;
5912
5913 virtual void addChild( Ptr<ITracker> const& child ) = 0;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005914 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0;
Phil Nash7e346192015-11-03 08:00:43 +00005915 virtual void openChild() = 0;
Phil Nash92b141e2016-04-28 08:13:00 +01005916
5917 // Debug/ checking
5918 virtual bool isSectionTracker() const = 0;
5919 virtual bool isIndexTracker() const = 0;
Phil Nash7e346192015-11-03 08:00:43 +00005920 };
5921
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005922 class TrackerContext {
Phil Nash7e346192015-11-03 08:00:43 +00005923
Phil Nash8a52a392013-07-25 08:12:03 +01005924 enum RunState {
5925 NotStarted,
5926 Executing,
Phil Nash7e346192015-11-03 08:00:43 +00005927 CompletedCycle
Phil Nasha695eb92012-08-13 07:46:10 +01005928 };
5929
Phil Nash7e346192015-11-03 08:00:43 +00005930 Ptr<ITracker> m_rootTracker;
5931 ITracker* m_currentTracker;
5932 RunState m_runState;
5933
5934 public:
5935
5936 static TrackerContext& instance() {
5937 static TrackerContext s_instance;
5938 return s_instance;
5939 }
5940
5941 TrackerContext()
5942 : m_currentTracker( CATCH_NULL ),
5943 m_runState( NotStarted )
Phil Nasha695eb92012-08-13 07:46:10 +01005944 {}
5945
Phil Nash7e346192015-11-03 08:00:43 +00005946 ITracker& startRun();
Phil Nasha695eb92012-08-13 07:46:10 +01005947
Phil Nash7e346192015-11-03 08:00:43 +00005948 void endRun() {
5949 m_rootTracker.reset();
5950 m_currentTracker = CATCH_NULL;
5951 m_runState = NotStarted;
Phil Nasha695eb92012-08-13 07:46:10 +01005952 }
Phil Nash3b18d9e2015-06-30 18:26:09 +01005953
Phil Nash7e346192015-11-03 08:00:43 +00005954 void startCycle() {
5955 m_currentTracker = m_rootTracker.get();
5956 m_runState = Executing;
Phil Nasha695eb92012-08-13 07:46:10 +01005957 }
Phil Nash7e346192015-11-03 08:00:43 +00005958 void completeCycle() {
5959 m_runState = CompletedCycle;
5960 }
5961
5962 bool completedCycle() const {
5963 return m_runState == CompletedCycle;
5964 }
5965 ITracker& currentTracker() {
5966 return *m_currentTracker;
5967 }
5968 void setCurrentTracker( ITracker* tracker ) {
5969 m_currentTracker = tracker;
5970 }
5971 };
5972
5973 class TrackerBase : public ITracker {
5974 protected:
5975 enum CycleState {
5976 NotStarted,
5977 Executing,
5978 ExecutingChildren,
5979 NeedsAnotherRun,
5980 CompletedSuccessfully,
5981 Failed
5982 };
5983 class TrackerHasName {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005984 NameAndLocation m_nameAndLocation;
Phil Nash7e346192015-11-03 08:00:43 +00005985 public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005986 TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
Phil Nash7e346192015-11-03 08:00:43 +00005987 bool operator ()( Ptr<ITracker> const& tracker ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005988 return
5989 tracker->nameAndLocation().name == m_nameAndLocation.name &&
5990 tracker->nameAndLocation().location == m_nameAndLocation.location;
Phil Nash7e346192015-11-03 08:00:43 +00005991 }
5992 };
5993 typedef std::vector<Ptr<ITracker> > Children;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005994 NameAndLocation m_nameAndLocation;
Phil Nash7e346192015-11-03 08:00:43 +00005995 TrackerContext& m_ctx;
5996 ITracker* m_parent;
5997 Children m_children;
5998 CycleState m_runState;
5999 public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006000 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
6001 : m_nameAndLocation( nameAndLocation ),
Phil Nash7e346192015-11-03 08:00:43 +00006002 m_ctx( ctx ),
6003 m_parent( parent ),
6004 m_runState( NotStarted )
6005 {}
6006 virtual ~TrackerBase();
6007
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006008 virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE {
6009 return m_nameAndLocation;
Phil Nash7e346192015-11-03 08:00:43 +00006010 }
6011 virtual bool isComplete() const CATCH_OVERRIDE {
6012 return m_runState == CompletedSuccessfully || m_runState == Failed;
6013 }
6014 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
6015 return m_runState == CompletedSuccessfully;
6016 }
6017 virtual bool isOpen() const CATCH_OVERRIDE {
6018 return m_runState != NotStarted && !isComplete();
6019 }
6020 virtual bool hasChildren() const CATCH_OVERRIDE {
Phil Nash8a52a392013-07-25 08:12:03 +01006021 return !m_children.empty();
Phil Nasha1fbfea2012-12-01 23:57:18 +00006022 }
6023
Phil Nash7e346192015-11-03 08:00:43 +00006024 virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
6025 m_children.push_back( child );
6026 }
Phil Nasha695eb92012-08-13 07:46:10 +01006027
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006028 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE {
6029 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
Phil Nash7e346192015-11-03 08:00:43 +00006030 return( it != m_children.end() )
6031 ? it->get()
6032 : CATCH_NULL;
6033 }
6034 virtual ITracker& parent() CATCH_OVERRIDE {
6035 assert( m_parent ); // Should always be non-null except for root
6036 return *m_parent;
6037 }
6038
6039 virtual void openChild() CATCH_OVERRIDE {
6040 if( m_runState != ExecutingChildren ) {
Phil Nash3b18d9e2015-06-30 18:26:09 +01006041 m_runState = ExecutingChildren;
Phil Nash7e346192015-11-03 08:00:43 +00006042 if( m_parent )
6043 m_parent->openChild();
Phil Nash3b18d9e2015-06-30 18:26:09 +01006044 }
Phil Nasha695eb92012-08-13 07:46:10 +01006045 }
Phil Nash92b141e2016-04-28 08:13:00 +01006046
6047 virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
6048 virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
6049
Phil Nash7e346192015-11-03 08:00:43 +00006050 void open() {
6051 m_runState = Executing;
6052 moveToThis();
6053 if( m_parent )
6054 m_parent->openChild();
Phil Nasha695eb92012-08-13 07:46:10 +01006055 }
6056
Phil Nash7e346192015-11-03 08:00:43 +00006057 virtual void close() CATCH_OVERRIDE {
Phil Nasha695eb92012-08-13 07:46:10 +01006058
Phil Nash7e346192015-11-03 08:00:43 +00006059 // Close any still open children (e.g. generators)
6060 while( &m_ctx.currentTracker() != this )
6061 m_ctx.currentTracker().close();
6062
6063 switch( m_runState ) {
6064 case NotStarted:
6065 case CompletedSuccessfully:
6066 case Failed:
6067 throw std::logic_error( "Illogical state" );
6068
6069 case NeedsAnotherRun:
6070 break;;
6071
6072 case Executing:
6073 m_runState = CompletedSuccessfully;
6074 break;
6075 case ExecutingChildren:
6076 if( m_children.empty() || m_children.back()->isComplete() )
6077 m_runState = CompletedSuccessfully;
6078 break;
6079
6080 default:
6081 throw std::logic_error( "Unexpected state" );
Phil Nash8a52a392013-07-25 08:12:03 +01006082 }
Phil Nash7e346192015-11-03 08:00:43 +00006083 moveToParent();
6084 m_ctx.completeCycle();
6085 }
6086 virtual void fail() CATCH_OVERRIDE {
6087 m_runState = Failed;
6088 if( m_parent )
6089 m_parent->markAsNeedingAnotherRun();
6090 moveToParent();
6091 m_ctx.completeCycle();
6092 }
6093 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
6094 m_runState = NeedsAnotherRun;
6095 }
Phil Nasha695eb92012-08-13 07:46:10 +01006096 private:
Phil Nash7e346192015-11-03 08:00:43 +00006097 void moveToParent() {
6098 assert( m_parent );
6099 m_ctx.setCurrentTracker( m_parent );
Phil Nash8a52a392013-07-25 08:12:03 +01006100 }
Phil Nash7e346192015-11-03 08:00:43 +00006101 void moveToThis() {
6102 m_ctx.setCurrentTracker( this );
Phil Nash8a52a392013-07-25 08:12:03 +01006103 }
Phil Nasha695eb92012-08-13 07:46:10 +01006104 };
Phil Nash8a52a392013-07-25 08:12:03 +01006105
Phil Nash7e346192015-11-03 08:00:43 +00006106 class SectionTracker : public TrackerBase {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006107 std::vector<std::string> m_filters;
Phil Nash7e346192015-11-03 08:00:43 +00006108 public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006109 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
6110 : TrackerBase( nameAndLocation, ctx, parent )
6111 {
6112 if( parent ) {
6113 while( !parent->isSectionTracker() )
6114 parent = &parent->parent();
6115
6116 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
6117 addNextFilters( parentSection.m_filters );
6118 }
6119 }
Phil Nash7e346192015-11-03 08:00:43 +00006120 virtual ~SectionTracker();
Phil Nash8a52a392013-07-25 08:12:03 +01006121
Phil Nash92b141e2016-04-28 08:13:00 +01006122 virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
6123
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006124 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
Phil Nash7e346192015-11-03 08:00:43 +00006125 SectionTracker* section = CATCH_NULL;
6126
6127 ITracker& currentTracker = ctx.currentTracker();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006128 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
Phil Nash92b141e2016-04-28 08:13:00 +01006129 assert( childTracker );
6130 assert( childTracker->isSectionTracker() );
6131 section = static_cast<SectionTracker*>( childTracker );
Phil Nash7e346192015-11-03 08:00:43 +00006132 }
6133 else {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006134 section = new SectionTracker( nameAndLocation, ctx, &currentTracker );
Phil Nash7e346192015-11-03 08:00:43 +00006135 currentTracker.addChild( section );
6136 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006137 if( !ctx.completedCycle() )
6138 section->tryOpen();
Phil Nash7e346192015-11-03 08:00:43 +00006139 return *section;
6140 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006141
6142 void tryOpen() {
6143 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
6144 open();
6145 }
6146
6147 void addInitialFilters( std::vector<std::string> const& filters ) {
6148 if( !filters.empty() ) {
6149 m_filters.push_back(""); // Root - should never be consulted
6150 m_filters.push_back(""); // Test Case - not a section filter
6151 std::copy( filters.begin(), filters.end(), std::back_inserter( m_filters ) );
6152 }
6153 }
6154 void addNextFilters( std::vector<std::string> const& filters ) {
6155 if( filters.size() > 1 )
6156 std::copy( filters.begin()+1, filters.end(), std::back_inserter( m_filters ) );
6157 }
Phil Nash7e346192015-11-03 08:00:43 +00006158 };
6159
6160 class IndexTracker : public TrackerBase {
6161 int m_size;
6162 int m_index;
6163 public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006164 IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
6165 : TrackerBase( nameAndLocation, ctx, parent ),
Phil Nash7e346192015-11-03 08:00:43 +00006166 m_size( size ),
6167 m_index( -1 )
6168 {}
6169 virtual ~IndexTracker();
6170
Phil Nash92b141e2016-04-28 08:13:00 +01006171 virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
6172
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006173 static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
Phil Nash7e346192015-11-03 08:00:43 +00006174 IndexTracker* tracker = CATCH_NULL;
6175
6176 ITracker& currentTracker = ctx.currentTracker();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006177 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
Phil Nash92b141e2016-04-28 08:13:00 +01006178 assert( childTracker );
6179 assert( childTracker->isIndexTracker() );
6180 tracker = static_cast<IndexTracker*>( childTracker );
Phil Nash7e346192015-11-03 08:00:43 +00006181 }
6182 else {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006183 tracker = new IndexTracker( nameAndLocation, ctx, &currentTracker, size );
Phil Nash7e346192015-11-03 08:00:43 +00006184 currentTracker.addChild( tracker );
6185 }
6186
6187 if( !ctx.completedCycle() && !tracker->isComplete() ) {
6188 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
6189 tracker->moveNext();
6190 tracker->open();
6191 }
6192
6193 return *tracker;
6194 }
6195
6196 int index() const { return m_index; }
6197
6198 void moveNext() {
6199 m_index++;
6200 m_children.clear();
6201 }
6202
6203 virtual void close() CATCH_OVERRIDE {
6204 TrackerBase::close();
6205 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
6206 m_runState = Executing;
6207 }
6208 };
6209
6210 inline ITracker& TrackerContext::startRun() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006211 m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL );
Phil Nash7e346192015-11-03 08:00:43 +00006212 m_currentTracker = CATCH_NULL;
6213 m_runState = Executing;
6214 return *m_rootTracker;
6215 }
6216
6217} // namespace TestCaseTracking
6218
6219using TestCaseTracking::ITracker;
6220using TestCaseTracking::TrackerContext;
6221using TestCaseTracking::SectionTracker;
6222using TestCaseTracking::IndexTracker;
Phil Nash8a52a392013-07-25 08:12:03 +01006223
6224} // namespace Catch
Phil Nasha695eb92012-08-13 07:46:10 +01006225
Phil Nash93b61e12014-08-22 19:35:41 +01006226// #included from: catch_fatal_condition.hpp
6227#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
6228
6229namespace Catch {
6230
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006231 // Report the error condition
6232 inline void reportFatal( std::string const& message ) {
Phil Nash93b61e12014-08-22 19:35:41 +01006233 IContext& context = Catch::getCurrentContext();
6234 IResultCapture* resultCapture = context.getResultCapture();
6235 resultCapture->handleFatalErrorCondition( message );
Phil Nash93b61e12014-08-22 19:35:41 +01006236 }
6237
6238} // namespace Catch
6239
6240#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006241// #included from: catch_windows_h_proxy.h
Phil Nash93b61e12014-08-22 19:35:41 +01006242
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006243#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED
6244
6245#ifdef CATCH_DEFINES_NOMINMAX
6246# define NOMINMAX
6247#endif
6248#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
6249# define WIN32_LEAN_AND_MEAN
6250#endif
6251
6252#ifdef __AFXDLL
6253#include <AfxWin.h>
6254#else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006255#include <windows.h>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006256#endif
6257
6258#ifdef CATCH_DEFINES_NOMINMAX
6259# undef NOMINMAX
6260#endif
6261#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
6262# undef WIN32_LEAN_AND_MEAN
6263#endif
6264
6265
6266# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
6267
6268namespace Catch {
6269 struct FatalConditionHandler {
6270 void reset() {}
6271 };
6272}
6273
6274# else // CATCH_CONFIG_WINDOWS_SEH is defined
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006275
Phil Nash93b61e12014-08-22 19:35:41 +01006276namespace Catch {
6277
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006278 struct SignalDefs { DWORD id; const char* name; };
6279 extern SignalDefs signalDefs[];
6280 // There is no 1-1 mapping between signals and windows exceptions.
6281 // Windows can easily distinguish between SO and SigSegV,
6282 // but SigInt, SigTerm, etc are handled differently.
6283 SignalDefs signalDefs[] = {
6284 { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
6285 { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
6286 { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
6287 { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
6288 };
6289
Phil Nashe54ac702014-10-21 07:25:26 +01006290 struct FatalConditionHandler {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006291
6292 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
6293 for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
6294 if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006295 reset();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006296 reportFatal(signalDefs[i].name);
6297 }
6298 }
6299 // If its not an exception we care about, pass it along.
6300 // This stops us from eating debugger breaks etc.
6301 return EXCEPTION_CONTINUE_SEARCH;
6302 }
6303
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006304 FatalConditionHandler() {
6305 isSet = true;
6306 // 32k seems enough for Catch to handle stack overflow,
6307 // but the value was found experimentally, so there is no strong guarantee
6308 guaranteeSize = 32 * 1024;
6309 exceptionHandlerHandle = CATCH_NULL;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006310 // Register as first handler in current chain
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006311 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006312 // Pass in guarantee size to be filled
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006313 SetThreadStackGuarantee(&guaranteeSize);
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006314 }
6315
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006316 static void reset() {
6317 if (isSet) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006318 // Unregister handler and restore the old guarantee
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006319 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
6320 SetThreadStackGuarantee(&guaranteeSize);
6321 exceptionHandlerHandle = CATCH_NULL;
6322 isSet = false;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006323 }
6324 }
6325
6326 ~FatalConditionHandler() {
6327 reset();
6328 }
6329 private:
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006330 static bool isSet;
6331 static ULONG guaranteeSize;
6332 static PVOID exceptionHandlerHandle;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006333 };
Phil Nash93b61e12014-08-22 19:35:41 +01006334
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006335 bool FatalConditionHandler::isSet = false;
6336 ULONG FatalConditionHandler::guaranteeSize = 0;
6337 PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL;
6338
Phil Nash93b61e12014-08-22 19:35:41 +01006339} // namespace Catch
6340
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006341# endif // CATCH_CONFIG_WINDOWS_SEH
6342
Phil Nash93b61e12014-08-22 19:35:41 +01006343#else // Not Windows - assumed to be POSIX compatible //////////////////////////
6344
Phil Nash0952b762017-02-28 14:19:09 +00006345# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
6346
6347namespace Catch {
6348 struct FatalConditionHandler {
6349 void reset() {}
6350 };
6351}
6352
6353# else // CATCH_CONFIG_POSIX_SIGNALS is defined
6354
Phil Nash93b61e12014-08-22 19:35:41 +01006355#include <signal.h>
6356
6357namespace Catch {
6358
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006359 struct SignalDefs {
6360 int id;
6361 const char* name;
6362 };
Phil Nash93b61e12014-08-22 19:35:41 +01006363 extern SignalDefs signalDefs[];
6364 SignalDefs signalDefs[] = {
6365 { SIGINT, "SIGINT - Terminal interrupt signal" },
6366 { SIGILL, "SIGILL - Illegal instruction signal" },
6367 { SIGFPE, "SIGFPE - Floating point error signal" },
6368 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
6369 { SIGTERM, "SIGTERM - Termination request signal" },
6370 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006371 };
Phil Nash93b61e12014-08-22 19:35:41 +01006372
6373 struct FatalConditionHandler {
6374
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006375 static bool isSet;
6376 static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
6377 static stack_t oldSigStack;
6378 static char altStackMem[SIGSTKSZ];
6379
Phil Nash93b61e12014-08-22 19:35:41 +01006380 static void handleSignal( int sig ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006381 std::string name = "<unknown signal>";
6382 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
6383 SignalDefs &def = signalDefs[i];
6384 if (sig == def.id) {
6385 name = def.name;
6386 break;
6387 }
6388 }
6389 reset();
6390 reportFatal(name);
6391 raise( sig );
Phil Nash93b61e12014-08-22 19:35:41 +01006392 }
6393
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006394 FatalConditionHandler() {
6395 isSet = true;
6396 stack_t sigStack;
6397 sigStack.ss_sp = altStackMem;
6398 sigStack.ss_size = SIGSTKSZ;
6399 sigStack.ss_flags = 0;
6400 sigaltstack(&sigStack, &oldSigStack);
6401 struct sigaction sa = { 0 };
6402
6403 sa.sa_handler = handleSignal;
6404 sa.sa_flags = SA_ONSTACK;
6405 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
6406 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
Phil Nash85b4e942014-10-02 18:51:05 +01006407 }
6408 }
6409
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006410 ~FatalConditionHandler() {
6411 reset();
6412 }
6413 static void reset() {
6414 if( isSet ) {
6415 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
6416 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
6417 sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
6418 }
6419 // Return the old stack
6420 sigaltstack(&oldSigStack, CATCH_NULL);
6421 isSet = false;
6422 }
6423 }
Phil Nash93b61e12014-08-22 19:35:41 +01006424 };
6425
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006426 bool FatalConditionHandler::isSet = false;
6427 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
6428 stack_t FatalConditionHandler::oldSigStack = {};
6429 char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
6430
Phil Nash93b61e12014-08-22 19:35:41 +01006431} // namespace Catch
6432
Phil Nash0952b762017-02-28 14:19:09 +00006433# endif // CATCH_CONFIG_POSIX_SIGNALS
6434
Phil Nash93b61e12014-08-22 19:35:41 +01006435#endif // not Windows
6436
Phil Nasha695eb92012-08-13 07:46:10 +01006437#include <set>
6438#include <string>
6439
6440namespace Catch {
6441
6442 class StreamRedirect {
6443
6444 public:
6445 StreamRedirect( std::ostream& stream, std::string& targetString )
6446 : m_stream( stream ),
6447 m_prevBuf( stream.rdbuf() ),
6448 m_targetString( targetString )
6449 {
6450 stream.rdbuf( m_oss.rdbuf() );
6451 }
6452
6453 ~StreamRedirect() {
6454 m_targetString += m_oss.str();
6455 m_stream.rdbuf( m_prevBuf );
6456 }
6457
6458 private:
6459 std::ostream& m_stream;
6460 std::streambuf* m_prevBuf;
6461 std::ostringstream m_oss;
6462 std::string& m_targetString;
6463 };
6464
6465 ///////////////////////////////////////////////////////////////////////////
6466
Phil Nash786959d2013-06-07 19:07:50 +01006467 class RunContext : public IResultCapture, public IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01006468
Phil Nash786959d2013-06-07 19:07:50 +01006469 RunContext( RunContext const& );
6470 void operator =( RunContext const& );
Phil Nasha695eb92012-08-13 07:46:10 +01006471
6472 public:
6473
Phil Nashb971fe72015-07-02 08:21:38 +01006474 explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
6475 : m_runInfo( _config->name() ),
Phil Nasha1fbfea2012-12-01 23:57:18 +00006476 m_context( getCurrentMutableContext() ),
Phil Nashb971fe72015-07-02 08:21:38 +01006477 m_activeTestCase( CATCH_NULL ),
6478 m_config( _config ),
Phil Nash7e346192015-11-03 08:00:43 +00006479 m_reporter( reporter )
Phil Nasha695eb92012-08-13 07:46:10 +01006480 {
6481 m_context.setRunner( this );
Phil Nash786959d2013-06-07 19:07:50 +01006482 m_context.setConfig( m_config );
Phil Nasha695eb92012-08-13 07:46:10 +01006483 m_context.setResultCapture( this );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006484 m_reporter->testRunStarting( m_runInfo );
Phil Nasha695eb92012-08-13 07:46:10 +01006485 }
6486
Phil Nash786959d2013-06-07 19:07:50 +01006487 virtual ~RunContext() {
Phil Nash2e7d9662013-01-16 09:44:43 +00006488 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
Phil Nasha695eb92012-08-13 07:46:10 +01006489 }
6490
Phil Nash2e7d9662013-01-16 09:44:43 +00006491 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
6492 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006493 }
Phil Nash2e7d9662013-01-16 09:44:43 +00006494 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
6495 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006496 }
Phil Nasha695eb92012-08-13 07:46:10 +01006497
Phil Nash8defc712013-04-24 19:10:02 +01006498 Totals runTest( TestCase const& testCase ) {
Phil Nasha695eb92012-08-13 07:46:10 +01006499 Totals prevTotals = m_totals;
6500
6501 std::string redirectedCout;
6502 std::string redirectedCerr;
6503
Phil Nasha1fbfea2012-12-01 23:57:18 +00006504 TestCaseInfo testInfo = testCase.getTestCaseInfo();
Phil Nasha695eb92012-08-13 07:46:10 +01006505
Phil Nasha1fbfea2012-12-01 23:57:18 +00006506 m_reporter->testCaseStarting( testInfo );
6507
Phil Nash8a52a392013-07-25 08:12:03 +01006508 m_activeTestCase = &testCase;
Phil Nasha695eb92012-08-13 07:46:10 +01006509
6510 do {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006511 ITracker& rootTracker = m_trackerContext.startRun();
Phil Nashd08cee22017-02-13 16:15:42 +00006512 assert( rootTracker.isSectionTracker() );
6513 static_cast<SectionTracker&>( rootTracker ).addInitialFilters( m_config->getSectionsToRun() );
Phil Nasha695eb92012-08-13 07:46:10 +01006514 do {
Phil Nash7e346192015-11-03 08:00:43 +00006515 m_trackerContext.startCycle();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006516 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01006517 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nasha695eb92012-08-13 07:46:10 +01006518 }
Phil Nash7e346192015-11-03 08:00:43 +00006519 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
Phil Nasha695eb92012-08-13 07:46:10 +01006520 }
Phil Nash7e346192015-11-03 08:00:43 +00006521 // !TBD: deprecated - this will be replaced by indexed trackers
Phil Nasha695eb92012-08-13 07:46:10 +01006522 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
6523
Phil Nash28463672012-11-21 18:06:13 +00006524 Totals deltaTotals = m_totals.delta( prevTotals );
Phil Nashc984fc32016-03-15 07:24:26 +00006525 if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
6526 deltaTotals.assertions.failed++;
6527 deltaTotals.testCases.passed--;
6528 deltaTotals.testCases.failed++;
6529 }
Phil Nash28463672012-11-21 18:06:13 +00006530 m_totals.testCases += deltaTotals.testCases;
Phil Nash2e7d9662013-01-16 09:44:43 +00006531 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6532 deltaTotals,
6533 redirectedCout,
6534 redirectedCerr,
Phil Nash2e7d9662013-01-16 09:44:43 +00006535 aborting() ) );
Phil Nash28463672012-11-21 18:06:13 +00006536
Phil Nashb971fe72015-07-02 08:21:38 +01006537 m_activeTestCase = CATCH_NULL;
Phil Nash7e346192015-11-03 08:00:43 +00006538 m_testCaseTracker = CATCH_NULL;
Phil Nasha695eb92012-08-13 07:46:10 +01006539
Phil Nash5bc030d2012-08-16 18:48:50 +01006540 return deltaTotals;
Phil Nasha695eb92012-08-13 07:46:10 +01006541 }
6542
Phil Nash786959d2013-06-07 19:07:50 +01006543 Ptr<IConfig const> config() const {
Phil Nasha695eb92012-08-13 07:46:10 +01006544 return m_config;
6545 }
6546
6547 private: // IResultCapture
6548
Phil Nash8defc712013-04-24 19:10:02 +01006549 virtual void assertionEnded( AssertionResult const& result ) {
Phil Nasha695eb92012-08-13 07:46:10 +01006550 if( result.getResultType() == ResultWas::Ok ) {
6551 m_totals.assertions.passed++;
6552 }
Phil Nash90a35942012-11-13 22:04:29 +00006553 else if( !result.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01006554 m_totals.assertions.failed++;
Phil Nasha695eb92012-08-13 07:46:10 +01006555 }
6556
Phil Nashb5fd5a62013-06-28 17:09:57 +01006557 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
6558 m_messages.clear();
Phil Nasha90a88a2012-11-19 19:59:10 +00006559
Phil Nasha2773812013-02-02 20:37:58 +00006560 // Reset working state
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006561 m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
Phil Nashab036682014-06-02 07:48:03 +01006562 m_lastResult = result;
Phil Nasha695eb92012-08-13 07:46:10 +01006563 }
6564
6565 virtual bool sectionStarted (
Phil Nasha1fbfea2012-12-01 23:57:18 +00006566 SectionInfo const& sectionInfo,
Phil Nasha695eb92012-08-13 07:46:10 +01006567 Counts& assertions
6568 )
6569 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006570 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) );
Phil Nash7e346192015-11-03 08:00:43 +00006571 if( !sectionTracker.isOpen() )
Phil Nasha695eb92012-08-13 07:46:10 +01006572 return false;
Phil Nash7e346192015-11-03 08:00:43 +00006573 m_activeSections.push_back( &sectionTracker );
Phil Nasha695eb92012-08-13 07:46:10 +01006574
Phil Nasha1fbfea2012-12-01 23:57:18 +00006575 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
Phil Nash90a35942012-11-13 22:04:29 +00006576
Phil Nasha1fbfea2012-12-01 23:57:18 +00006577 m_reporter->sectionStarting( sectionInfo );
6578
Phil Nasha695eb92012-08-13 07:46:10 +01006579 assertions = m_totals.assertions;
6580
6581 return true;
6582 }
Phil Nashaa7123b2013-08-15 19:01:00 +01006583 bool testForMissingAssertions( Counts& assertions ) {
Phil Nash7e346192015-11-03 08:00:43 +00006584 if( assertions.total() != 0 )
6585 return false;
Phil Nash9e421532015-11-03 17:06:54 +00006586 if( !m_config->warnAboutMissingAssertions() )
Phil Nash7e346192015-11-03 08:00:43 +00006587 return false;
6588 if( m_trackerContext.currentTracker().hasChildren() )
Phil Nashaa7123b2013-08-15 19:01:00 +01006589 return false;
6590 m_totals.assertions.failed++;
6591 assertions.failed++;
6592 return true;
6593 }
Phil Nasha695eb92012-08-13 07:46:10 +01006594
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006595 virtual void sectionEnded( SectionEndInfo const& endInfo ) {
6596 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
Phil Nashaa7123b2013-08-15 19:01:00 +01006597 bool missingAssertions = testForMissingAssertions( assertions );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006598
Phil Nash7e346192015-11-03 08:00:43 +00006599 if( !m_activeSections.empty() ) {
6600 m_activeSections.back()->close();
6601 m_activeSections.pop_back();
6602 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00006603
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006604 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
Phil Nasha2773812013-02-02 20:37:58 +00006605 m_messages.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01006606 }
6607
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006608 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
Phil Nash7e346192015-11-03 08:00:43 +00006609 if( m_unfinishedSections.empty() )
6610 m_activeSections.back()->fail();
6611 else
6612 m_activeSections.back()->close();
6613 m_activeSections.pop_back();
6614
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006615 m_unfinishedSections.push_back( endInfo );
6616 }
6617
Phil Nashb5fd5a62013-06-28 17:09:57 +01006618 virtual void pushScopedMessage( MessageInfo const& message ) {
6619 m_messages.push_back( message );
Phil Nasha695eb92012-08-13 07:46:10 +01006620 }
6621
Phil Nashb5fd5a62013-06-28 17:09:57 +01006622 virtual void popScopedMessage( MessageInfo const& message ) {
6623 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
Phil Nasha695eb92012-08-13 07:46:10 +01006624 }
6625
Phil Nasha695eb92012-08-13 07:46:10 +01006626 virtual std::string getCurrentTestName() const {
Phil Nash8a52a392013-07-25 08:12:03 +01006627 return m_activeTestCase
6628 ? m_activeTestCase->getTestCaseInfo().name
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006629 : std::string();
Phil Nasha695eb92012-08-13 07:46:10 +01006630 }
6631
Phil Nashce612bf2012-11-01 08:27:09 +00006632 virtual const AssertionResult* getLastResult() const {
Phil Nasha695eb92012-08-13 07:46:10 +01006633 return &m_lastResult;
6634 }
6635
Phil Nash93b61e12014-08-22 19:35:41 +01006636 virtual void handleFatalErrorCondition( std::string const& message ) {
6637 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
6638 resultBuilder.setResultType( ResultWas::FatalErrorCondition );
6639 resultBuilder << message;
6640 resultBuilder.captureExpression();
6641
6642 handleUnfinishedSections();
6643
6644 // Recreate section for test case (as we will lose the one that was in scope)
6645 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6646 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6647
6648 Counts assertions;
6649 assertions.failed = 1;
6650 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
6651 m_reporter->sectionEnded( testCaseSectionStats );
6652
6653 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
6654
6655 Totals deltaTotals;
6656 deltaTotals.testCases.failed = 1;
6657 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6658 deltaTotals,
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006659 std::string(),
6660 std::string(),
Phil Nash93b61e12014-08-22 19:35:41 +01006661 false ) );
6662 m_totals.testCases.failed++;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006663 testGroupEnded( std::string(), m_totals, 1, 1 );
Phil Nash93b61e12014-08-22 19:35:41 +01006664 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
6665 }
6666
Phil Nash56d5c422012-08-23 20:08:50 +01006667 public:
6668 // !TBD We need to do this another way!
Phil Nasha695eb92012-08-13 07:46:10 +01006669 bool aborting() const {
Phil Nash786959d2013-06-07 19:07:50 +01006670 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
Phil Nasha695eb92012-08-13 07:46:10 +01006671 }
6672
Phil Nash56d5c422012-08-23 20:08:50 +01006673 private:
6674
Phil Nasha695eb92012-08-13 07:46:10 +01006675 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
Phil Nash8a52a392013-07-25 08:12:03 +01006676 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
Phil Nashce562092014-07-09 07:40:37 +01006677 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
Phil Nash8a52a392013-07-25 08:12:03 +01006678 m_reporter->sectionStarting( testCaseSection );
Phil Nashaa7123b2013-08-15 19:01:00 +01006679 Counts prevAssertions = m_totals.assertions;
6680 double duration = 0;
Phil Nasha695eb92012-08-13 07:46:10 +01006681 try {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006682 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal );
Phil Nashd768b1b2013-02-04 00:05:16 +00006683
Phil Nash8f66e342015-07-02 23:03:13 +01006684 seedRng( *m_config );
Phil Nasha695eb92012-08-13 07:46:10 +01006685
Phil Nashaa7123b2013-08-15 19:01:00 +01006686 Timer timer;
6687 timer.start();
Phil Nasha1fbfea2012-12-01 23:57:18 +00006688 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
Phil Nash383d7c02014-10-02 19:08:19 +01006689 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
6690 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
Phil Nash93b61e12014-08-22 19:35:41 +01006691 invokeActiveTestCase();
Phil Nasha695eb92012-08-13 07:46:10 +01006692 }
6693 else {
Phil Nash93b61e12014-08-22 19:35:41 +01006694 invokeActiveTestCase();
Phil Nasha70fbe32012-08-31 08:10:36 +01006695 }
Phil Nashaa7123b2013-08-15 19:01:00 +01006696 duration = timer.getElapsedSeconds();
Phil Nasha695eb92012-08-13 07:46:10 +01006697 }
6698 catch( TestFailureException& ) {
6699 // This just means the test was aborted due to failure
6700 }
6701 catch(...) {
Phil Nash93b61e12014-08-22 19:35:41 +01006702 makeUnexpectedResultBuilder().useActiveException();
Phil Nasha695eb92012-08-13 07:46:10 +01006703 }
Phil Nash7e346192015-11-03 08:00:43 +00006704 m_testCaseTracker->close();
Phil Nash93b61e12014-08-22 19:35:41 +01006705 handleUnfinishedSections();
Phil Nashd768b1b2013-02-04 00:05:16 +00006706 m_messages.clear();
Phil Nashaa7123b2013-08-15 19:01:00 +01006707
6708 Counts assertions = m_totals.assertions - prevAssertions;
6709 bool missingAssertions = testForMissingAssertions( assertions );
6710
Phil Nash52e1e742014-07-03 08:11:38 +01006711 if( testCaseInfo.okToFail() ) {
6712 std::swap( assertions.failedButOk, assertions.failed );
6713 m_totals.assertions.failed -= assertions.failedButOk;
6714 m_totals.assertions.failedButOk += assertions.failedButOk;
6715 }
6716
Phil Nashaa7123b2013-08-15 19:01:00 +01006717 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
Phil Nash8a52a392013-07-25 08:12:03 +01006718 m_reporter->sectionEnded( testCaseSectionStats );
Phil Nasha695eb92012-08-13 07:46:10 +01006719 }
6720
Phil Nash93b61e12014-08-22 19:35:41 +01006721 void invokeActiveTestCase() {
6722 FatalConditionHandler fatalConditionHandler; // Handle signals
6723 m_activeTestCase->invoke();
Phil Nash85b4e942014-10-02 18:51:05 +01006724 fatalConditionHandler.reset();
Phil Nash93b61e12014-08-22 19:35:41 +01006725 }
6726
Phil Nasha695eb92012-08-13 07:46:10 +01006727 private:
Phil Nash93b61e12014-08-22 19:35:41 +01006728
6729 ResultBuilder makeUnexpectedResultBuilder() const {
6730 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
6731 m_lastAssertionInfo.lineInfo,
6732 m_lastAssertionInfo.capturedExpression.c_str(),
6733 m_lastAssertionInfo.resultDisposition );
6734 }
6735
6736 void handleUnfinishedSections() {
6737 // If sections ended prematurely due to an exception we stored their
6738 // infos here so we can tear them down outside the unwind process.
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006739 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
Phil Nash93b61e12014-08-22 19:35:41 +01006740 itEnd = m_unfinishedSections.rend();
6741 it != itEnd;
6742 ++it )
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006743 sectionEnded( *it );
Phil Nash93b61e12014-08-22 19:35:41 +01006744 m_unfinishedSections.clear();
6745 }
6746
Phil Nasha1fbfea2012-12-01 23:57:18 +00006747 TestRunInfo m_runInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01006748 IMutableContext& m_context;
Phil Nash8a52a392013-07-25 08:12:03 +01006749 TestCase const* m_activeTestCase;
Phil Nash7e346192015-11-03 08:00:43 +00006750 ITracker* m_testCaseTracker;
6751 ITracker* m_currentSectionTracker;
Phil Nashce612bf2012-11-01 08:27:09 +00006752 AssertionResult m_lastResult;
Phil Nasha695eb92012-08-13 07:46:10 +01006753
Phil Nash786959d2013-06-07 19:07:50 +01006754 Ptr<IConfig const> m_config;
Phil Nasha695eb92012-08-13 07:46:10 +01006755 Totals m_totals;
Phil Nasha1fbfea2012-12-01 23:57:18 +00006756 Ptr<IStreamingReporter> m_reporter;
Phil Nasha2773812013-02-02 20:37:58 +00006757 std::vector<MessageInfo> m_messages;
Phil Nash90a35942012-11-13 22:04:29 +00006758 AssertionInfo m_lastAssertionInfo;
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006759 std::vector<SectionEndInfo> m_unfinishedSections;
Phil Nash7e346192015-11-03 08:00:43 +00006760 std::vector<ITracker*> m_activeSections;
6761 TrackerContext m_trackerContext;
Phil Nasha695eb92012-08-13 07:46:10 +01006762 };
6763
Phil Nashab036682014-06-02 07:48:03 +01006764 IResultCapture& getResultCapture() {
6765 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
6766 return *capture;
6767 else
6768 throw std::logic_error( "No result capture instance" );
6769 }
6770
Phil Nasha695eb92012-08-13 07:46:10 +01006771} // end namespace Catch
6772
Phil Nash7673a302012-11-15 22:15:41 +00006773// #included from: internal/catch_version.h
6774#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
6775
6776namespace Catch {
6777
6778 // Versioning information
6779 struct Version {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006780 Version( unsigned int _majorVersion,
6781 unsigned int _minorVersion,
Phil Nash21f7ef62015-06-29 18:05:23 +01006782 unsigned int _patchNumber,
6783 std::string const& _branchName,
6784 unsigned int _buildNumber );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006785
Phil Nash9d469b62014-04-18 08:30:31 +01006786 unsigned int const majorVersion;
6787 unsigned int const minorVersion;
Phil Nash21f7ef62015-06-29 18:05:23 +01006788 unsigned int const patchNumber;
6789
6790 // buildNumber is only used if branchName is not null
6791 std::string const branchName;
Phil Nash9d469b62014-04-18 08:30:31 +01006792 unsigned int const buildNumber;
Phil Nash21f7ef62015-06-29 18:05:23 +01006793
6794 friend std::ostream& operator << ( std::ostream& os, Version const& version );
Phil Nashdd26e882013-03-25 09:25:31 +00006795
Phil Nash503d5d02013-07-03 08:25:11 +01006796 private:
6797 void operator=( Version const& );
Phil Nash7673a302012-11-15 22:15:41 +00006798 };
6799
6800 extern Version libraryVersion;
6801}
6802
Phil Nash89d1e6c2011-05-24 08:23:02 +01006803#include <fstream>
6804#include <stdlib.h>
6805#include <limits>
6806
Phil Nash89d2a3f2012-05-16 15:09:17 +01006807namespace Catch {
6808
Phil Nashe73583d2015-08-07 17:30:34 +01006809 Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006810 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
6811 if( !reporter ) {
6812 std::ostringstream oss;
6813 oss << "No reporter registered with name: '" << reporterName << "'";
6814 throw std::domain_error( oss.str() );
Phil Nash56d5c422012-08-23 20:08:50 +01006815 }
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006816 return reporter;
6817 }
Phil Nash5bc030d2012-08-16 18:48:50 +01006818
Phil Nashe73583d2015-08-07 17:30:34 +01006819 Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
6820 std::vector<std::string> reporters = config->getReporterNames();
6821 if( reporters.empty() )
6822 reporters.push_back( "console" );
6823
6824 Ptr<IStreamingReporter> reporter;
6825 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
6826 it != itEnd;
6827 ++it )
6828 reporter = addReporter( reporter, createReporter( *it, config ) );
6829 return reporter;
6830 }
Phil Nash7e346192015-11-03 08:00:43 +00006831 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
Phil Nashe73583d2015-08-07 17:30:34 +01006832 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
6833 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
6834 it != itEnd;
6835 ++it )
6836 reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
6837 return reporters;
6838 }
6839
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006840 Totals runTests( Ptr<Config> const& config ) {
6841
Phil Nash7e346192015-11-03 08:00:43 +00006842 Ptr<IConfig const> iconfig = config.get();
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006843
Phil Nash7e346192015-11-03 08:00:43 +00006844 Ptr<IStreamingReporter> reporter = makeReporter( config );
6845 reporter = addListeners( iconfig, reporter );
6846
6847 RunContext context( iconfig, reporter );
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006848
6849 Totals totals;
6850
6851 context.testGroupStarting( config->name(), 1, 1 );
6852
6853 TestSpec testSpec = config->testSpec();
6854 if( !testSpec.hasFilters() )
6855 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
6856
Phil Nash7e346192015-11-03 08:00:43 +00006857 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
Phil Nashe73583d2015-08-07 17:30:34 +01006858 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006859 it != itEnd;
6860 ++it ) {
Phil Nash7e346192015-11-03 08:00:43 +00006861 if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006862 totals += context.runTest( *it );
Phil Nashe73583d2015-08-07 17:30:34 +01006863 else
6864 reporter->skipTest( *it );
Phil Nash5bc030d2012-08-16 18:48:50 +01006865 }
Phil Nash06e959b2012-05-25 08:52:05 +01006866
Phil Nash7e346192015-11-03 08:00:43 +00006867 context.testGroupEnded( iconfig->name(), totals, 1, 1 );
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006868 return totals;
6869 }
Phil Nash56d5c422012-08-23 20:08:50 +01006870
Phil Nashe73583d2015-08-07 17:30:34 +01006871 void applyFilenamesAsTags( IConfig const& config ) {
6872 std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
Phil Nashb971fe72015-07-02 08:21:38 +01006873 for(std::size_t i = 0; i < tests.size(); ++i ) {
6874 TestCase& test = const_cast<TestCase&>( tests[i] );
6875 std::set<std::string> tags = test.tags;
Phil Nash786959d2013-06-07 19:07:50 +01006876
Phil Nashb971fe72015-07-02 08:21:38 +01006877 std::string filename = test.lineInfo.file;
Phil Nashc1ca0fd2015-07-03 18:30:25 +01006878 std::string::size_type lastSlash = filename.find_last_of( "\\/" );
Phil Nashb971fe72015-07-02 08:21:38 +01006879 if( lastSlash != std::string::npos )
6880 filename = filename.substr( lastSlash+1 );
Phil Nash56d5c422012-08-23 20:08:50 +01006881
Phil Nashb971fe72015-07-02 08:21:38 +01006882 std::string::size_type lastDot = filename.find_last_of( "." );
6883 if( lastDot != std::string::npos )
6884 filename = filename.substr( 0, lastDot );
Phil Nash65cc14c2014-05-16 18:54:48 +01006885
Phil Nashe6b365d2015-07-07 08:25:15 +01006886 tags.insert( "#" + filename );
Phil Nashb971fe72015-07-02 08:21:38 +01006887 setTags( test, tags );
Phil Nash89d1e6c2011-05-24 08:23:02 +01006888 }
Phil Nashb971fe72015-07-02 08:21:38 +01006889 }
Phil Nash56d5c422012-08-23 20:08:50 +01006890
Phil Nashe54ac702014-10-21 07:25:26 +01006891 class Session : NonCopyable {
Phil Nash786959d2013-06-07 19:07:50 +01006892 static bool alreadyInstantiated;
Phil Nash56d5c422012-08-23 20:08:50 +01006893
Phil Nash786959d2013-06-07 19:07:50 +01006894 public:
Phil Nash56d5c422012-08-23 20:08:50 +01006895
Phil Nash786959d2013-06-07 19:07:50 +01006896 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
6897
6898 Session()
6899 : m_cli( makeCommandLineParser() ) {
6900 if( alreadyInstantiated ) {
6901 std::string msg = "Only one instance of Catch::Session can ever be used";
Phil Nash383d7c02014-10-02 19:08:19 +01006902 Catch::cerr() << msg << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01006903 throw std::logic_error( msg );
Phil Nash56d5c422012-08-23 20:08:50 +01006904 }
Phil Nash786959d2013-06-07 19:07:50 +01006905 alreadyInstantiated = true;
Phil Nash56d5c422012-08-23 20:08:50 +01006906 }
Phil Nash786959d2013-06-07 19:07:50 +01006907 ~Session() {
Phil Nash3b80af72012-08-09 07:47:30 +01006908 Catch::cleanUp();
Phil Nash89d1e6c2011-05-24 08:23:02 +01006909 }
6910
Phil Nash786959d2013-06-07 19:07:50 +01006911 void showHelp( std::string const& processName ) {
Phil Nash21f7ef62015-06-29 18:05:23 +01006912 Catch::cout() << "\nCatch v" << libraryVersion << "\n";
Phil Nash89d1e6c2011-05-24 08:23:02 +01006913
Phil Nash383d7c02014-10-02 19:08:19 +01006914 m_cli.usage( Catch::cout(), processName );
6915 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
Phil Nash3b80af72012-08-09 07:47:30 +01006916 }
Phil Nash3b80af72012-08-09 07:47:30 +01006917
Phil Nashe5537842016-04-25 18:56:50 +01006918 int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
Phil Nash786959d2013-06-07 19:07:50 +01006919 try {
Phil Nash91ef5f72013-12-20 19:06:26 +00006920 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
Phil Nashe5537842016-04-25 18:56:50 +01006921 m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
Phil Nash786959d2013-06-07 19:07:50 +01006922 if( m_configData.showHelp )
6923 showHelp( m_configData.processName );
6924 m_config.reset();
Phil Nash3b80af72012-08-09 07:47:30 +01006925 }
Phil Nash786959d2013-06-07 19:07:50 +01006926 catch( std::exception& ex ) {
Phil Nash46118712013-08-16 19:01:32 +01006927 {
6928 Colour colourGuard( Colour::Red );
Phil Nash21f7ef62015-06-29 18:05:23 +01006929 Catch::cerr()
6930 << "\nError(s) in input:\n"
6931 << Text( ex.what(), TextAttributes().setIndent(2) )
6932 << "\n\n";
Phil Nash46118712013-08-16 19:01:32 +01006933 }
Phil Nash383d7c02014-10-02 19:08:19 +01006934 m_cli.usage( Catch::cout(), m_configData.processName );
Phil Nash786959d2013-06-07 19:07:50 +01006935 return (std::numeric_limits<int>::max)();
6936 }
6937 return 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01006938 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01006939
Phil Nash786959d2013-06-07 19:07:50 +01006940 void useConfigData( ConfigData const& _configData ) {
6941 m_configData = _configData;
6942 m_config.reset();
6943 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01006944
Phil Nashe5537842016-04-25 18:56:50 +01006945 int run( int argc, char const* const* const argv ) {
Phil Nash786959d2013-06-07 19:07:50 +01006946
6947 int returnCode = applyCommandLine( argc, argv );
6948 if( returnCode == 0 )
6949 returnCode = run();
6950 return returnCode;
6951 }
6952
6953 int run() {
6954 if( m_configData.showHelp )
6955 return 0;
6956
6957 try
6958 {
6959 config(); // Force config to be constructed
Phil Nash6a8e8ad2014-09-15 18:40:24 +01006960
Phil Nash8f66e342015-07-02 23:03:13 +01006961 seedRng( *m_config );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01006962
Phil Nashe73583d2015-08-07 17:30:34 +01006963 if( m_configData.filenamesAsTags )
6964 applyFilenamesAsTags( *m_config );
Phil Nash786959d2013-06-07 19:07:50 +01006965
6966 // Handle list request
6967 if( Option<std::size_t> listed = list( config() ) )
6968 return static_cast<int>( *listed );
6969
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006970 return static_cast<int>( runTests( m_config ).assertions.failed );
Phil Nash786959d2013-06-07 19:07:50 +01006971 }
6972 catch( std::exception& ex ) {
Phil Nash383d7c02014-10-02 19:08:19 +01006973 Catch::cerr() << ex.what() << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01006974 return (std::numeric_limits<int>::max)();
6975 }
6976 }
6977
6978 Clara::CommandLine<ConfigData> const& cli() const {
6979 return m_cli;
6980 }
6981 std::vector<Clara::Parser::Token> const& unusedTokens() const {
6982 return m_unusedTokens;
6983 }
6984 ConfigData& configData() {
6985 return m_configData;
6986 }
6987 Config& config() {
6988 if( !m_config )
6989 m_config = new Config( m_configData );
6990 return *m_config;
6991 }
Phil Nash786959d2013-06-07 19:07:50 +01006992 private:
6993 Clara::CommandLine<ConfigData> m_cli;
6994 std::vector<Clara::Parser::Token> m_unusedTokens;
6995 ConfigData m_configData;
6996 Ptr<Config> m_config;
6997 };
6998
6999 bool Session::alreadyInstantiated = false;
Phil Nash89d1e6c2011-05-24 08:23:02 +01007000
7001} // end namespace Catch
7002
7003// #included from: catch_registry_hub.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007004#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01007005
Phil Nash89d1e6c2011-05-24 08:23:02 +01007006// #included from: catch_test_case_registry_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007007#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007008
7009#include <vector>
7010#include <set>
Phil Nash3b80af72012-08-09 07:47:30 +01007011#include <sstream>
Phil Nash96304542014-09-15 23:32:13 +01007012#include <algorithm>
Phil Nash3b80af72012-08-09 07:47:30 +01007013
7014namespace Catch {
7015
Phil Nashe73583d2015-08-07 17:30:34 +01007016 struct RandomNumberGenerator {
Phil Nashe27c4ee2016-10-26 12:08:26 +01007017 typedef std::ptrdiff_t result_type;
Phil Nashac220282016-06-09 08:19:23 +01007018
7019 result_type operator()( result_type n ) const { return std::rand() % n; }
7020
Phil Nash3b2f2062017-01-11 16:43:56 +00007021#ifdef CATCH_CONFIG_CPP11_SHUFFLE
Phil Nashac220282016-06-09 08:19:23 +01007022 static constexpr result_type min() { return 0; }
7023 static constexpr result_type max() { return 1000000; }
7024 result_type operator()() const { return std::rand() % max(); }
7025#endif
7026 template<typename V>
7027 static void shuffle( V& vector ) {
Phil Nash35f51052016-06-09 19:21:09 +01007028 RandomNumberGenerator rng;
Phil Nash3b2f2062017-01-11 16:43:56 +00007029#ifdef CATCH_CONFIG_CPP11_SHUFFLE
Phil Nash35f51052016-06-09 19:21:09 +01007030 std::shuffle( vector.begin(), vector.end(), rng );
Phil Nashac220282016-06-09 08:19:23 +01007031#else
Phil Nash35f51052016-06-09 19:21:09 +01007032 std::random_shuffle( vector.begin(), vector.end(), rng );
Phil Nashac220282016-06-09 08:19:23 +01007033#endif
7034 }
Phil Nashe73583d2015-08-07 17:30:34 +01007035 };
Phil Nashee3b2652014-09-18 18:25:10 +01007036
Phil Nashe73583d2015-08-07 17:30:34 +01007037 inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
7038
7039 std::vector<TestCase> sorted = unsortedTestCases;
7040
7041 switch( config.runOrder() ) {
7042 case RunTests::InLexicographicalOrder:
Phil Nashac220282016-06-09 08:19:23 +01007043 std::sort( sorted.begin(), sorted.end() );
Phil Nashe73583d2015-08-07 17:30:34 +01007044 break;
7045 case RunTests::InRandomOrder:
7046 {
7047 seedRng( config );
Phil Nashac220282016-06-09 08:19:23 +01007048 RandomNumberGenerator::shuffle( sorted );
Phil Nashe73583d2015-08-07 17:30:34 +01007049 }
7050 break;
7051 case RunTests::InDeclarationOrder:
7052 // already in declaration order
7053 break;
7054 }
7055 return sorted;
7056 }
7057 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
7058 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
7059 }
Phil Nashe73583d2015-08-07 17:30:34 +01007060
7061 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
7062 std::set<TestCase> seenFunctions;
7063 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
7064 it != itEnd;
7065 ++it ) {
7066 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
Phil Nashebf9f3b2016-05-10 19:09:59 +01007067 if( !prev.second ) {
7068 std::ostringstream ss;
7069
7070 ss << Colour( Colour::Red )
7071 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007072 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n'
Phil Nashebf9f3b2016-05-10 19:09:59 +01007073 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
7074
7075 throw std::runtime_error(ss.str());
Phil Nashe73583d2015-08-07 17:30:34 +01007076 }
7077 }
7078 }
7079
7080 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
7081 std::vector<TestCase> filtered;
Phil Nash8a05f462015-08-07 17:53:29 +01007082 filtered.reserve( testCases.size() );
7083 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
7084 it != itEnd;
7085 ++it )
7086 if( matchTest( *it, testSpec, config ) )
7087 filtered.push_back( *it );
Phil Nashe73583d2015-08-07 17:30:34 +01007088 return filtered;
7089 }
7090 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
7091 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
7092 }
7093
7094 class TestRegistry : public ITestCaseRegistry {
Phil Nash3b80af72012-08-09 07:47:30 +01007095 public:
Phil Nash981347b2015-12-09 18:11:48 +00007096 TestRegistry()
7097 : m_currentSortOrder( RunTests::InDeclarationOrder ),
7098 m_unnamedCount( 0 )
7099 {}
Phil Nash3b80af72012-08-09 07:47:30 +01007100 virtual ~TestRegistry();
7101
Phil Nash8defc712013-04-24 19:10:02 +01007102 virtual void registerTest( TestCase const& testCase ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007103 std::string name = testCase.getTestCaseInfo().name;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007104 if( name.empty() ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007105 std::ostringstream oss;
Phil Nash93906752013-03-16 20:21:51 +00007106 oss << "Anonymous test case " << ++m_unnamedCount;
Phil Nasha1fbfea2012-12-01 23:57:18 +00007107 return registerTest( testCase.withName( oss.str() ) );
Phil Nash3b80af72012-08-09 07:47:30 +01007108 }
Phil Nashe73583d2015-08-07 17:30:34 +01007109 m_functions.push_back( testCase );
Phil Nash3b80af72012-08-09 07:47:30 +01007110 }
7111
Phil Nash8defc712013-04-24 19:10:02 +01007112 virtual std::vector<TestCase> const& getAllTests() const {
Phil Nashe73583d2015-08-07 17:30:34 +01007113 return m_functions;
Phil Nash3b80af72012-08-09 07:47:30 +01007114 }
Phil Nashe73583d2015-08-07 17:30:34 +01007115 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
7116 if( m_sortedFunctions.empty() )
7117 enforceNoDuplicateTestCases( m_functions );
Phil Nash3b80af72012-08-09 07:47:30 +01007118
Phil Nashe73583d2015-08-07 17:30:34 +01007119 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
7120 m_sortedFunctions = sortTests( config, m_functions );
7121 m_currentSortOrder = config.runOrder();
Phil Nash3b80af72012-08-09 07:47:30 +01007122 }
Phil Nashe73583d2015-08-07 17:30:34 +01007123 return m_sortedFunctions;
Phil Nash92f08362014-12-22 20:18:05 +00007124 }
7125
7126 private:
Phil Nashe73583d2015-08-07 17:30:34 +01007127 std::vector<TestCase> m_functions;
7128 mutable RunTests::InWhatOrder m_currentSortOrder;
7129 mutable std::vector<TestCase> m_sortedFunctions;
Phil Nash3b80af72012-08-09 07:47:30 +01007130 size_t m_unnamedCount;
Phil Nash93a842e2015-07-13 06:36:07 +01007131 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
Phil Nash3b80af72012-08-09 07:47:30 +01007132 };
7133
7134 ///////////////////////////////////////////////////////////////////////////
7135
7136 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
7137 public:
7138
7139 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
7140
7141 virtual void invoke() const {
7142 m_fun();
7143 }
7144
7145 private:
7146 virtual ~FreeFunctionTestCase();
7147
7148 TestFunction m_fun;
7149 };
7150
Phil Nash8defc712013-04-24 19:10:02 +01007151 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
Phil Nash90a35942012-11-13 22:04:29 +00007152 std::string className = classOrQualifiedMethodName;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007153 if( startsWith( className, '&' ) )
Phil Nash90a35942012-11-13 22:04:29 +00007154 {
7155 std::size_t lastColons = className.rfind( "::" );
7156 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
7157 if( penultimateColons == std::string::npos )
7158 penultimateColons = 1;
7159 className = className.substr( penultimateColons, lastColons-penultimateColons );
7160 }
7161 return className;
7162 }
7163
Phil Nash7e15d9b2015-11-20 16:59:14 +00007164 void registerTestCase
7165 ( ITestCase* testCase,
7166 char const* classOrQualifiedMethodName,
7167 NameAndDesc const& nameAndDesc,
7168 SourceLineInfo const& lineInfo ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007169
Phil Nash7e15d9b2015-11-20 16:59:14 +00007170 getMutableRegistryHub().registerTest
7171 ( makeTestCase
7172 ( testCase,
7173 extractClassName( classOrQualifiedMethodName ),
7174 nameAndDesc.name,
7175 nameAndDesc.description,
7176 lineInfo ) );
7177 }
7178 void registerTestCaseFunction
7179 ( TestFunction function,
7180 SourceLineInfo const& lineInfo,
7181 NameAndDesc const& nameAndDesc ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01007182 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01007183 }
7184
Phil Nash7e15d9b2015-11-20 16:59:14 +00007185 ///////////////////////////////////////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01007186
Phil Nash7e15d9b2015-11-20 16:59:14 +00007187 AutoReg::AutoReg
7188 ( TestFunction function,
7189 SourceLineInfo const& lineInfo,
7190 NameAndDesc const& nameAndDesc ) {
7191 registerTestCaseFunction( function, lineInfo, nameAndDesc );
Phil Nash3b80af72012-08-09 07:47:30 +01007192 }
7193
Phil Nash7e15d9b2015-11-20 16:59:14 +00007194 AutoReg::~AutoReg() {}
7195
Phil Nash3b80af72012-08-09 07:47:30 +01007196} // end namespace Catch
7197
7198// #included from: catch_reporter_registry.hpp
7199#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
7200
7201#include <map>
7202
7203namespace Catch {
7204
7205 class ReporterRegistry : public IReporterRegistry {
7206
7207 public:
7208
Phil Nash19520152015-08-10 07:32:48 +01007209 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
Phil Nash3b80af72012-08-09 07:47:30 +01007210
Phil Nash7e346192015-11-03 08:00:43 +00007211 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007212 FactoryMap::const_iterator it = m_factories.find( name );
7213 if( it == m_factories.end() )
Phil Nashb971fe72015-07-02 08:21:38 +01007214 return CATCH_NULL;
Phil Nash786959d2013-06-07 19:07:50 +01007215 return it->second->create( ReporterConfig( config ) );
Phil Nash3b80af72012-08-09 07:47:30 +01007216 }
7217
Phil Nashe73583d2015-08-07 17:30:34 +01007218 void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007219 m_factories.insert( std::make_pair( name, factory ) );
7220 }
Phil Nashe73583d2015-08-07 17:30:34 +01007221 void registerListener( Ptr<IReporterFactory> const& factory ) {
7222 m_listeners.push_back( factory );
7223 }
Phil Nash3b80af72012-08-09 07:47:30 +01007224
Phil Nash19520152015-08-10 07:32:48 +01007225 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007226 return m_factories;
7227 }
Phil Nash19520152015-08-10 07:32:48 +01007228 virtual Listeners const& getListeners() const CATCH_OVERRIDE {
Phil Nashe73583d2015-08-07 17:30:34 +01007229 return m_listeners;
7230 }
Phil Nash3b80af72012-08-09 07:47:30 +01007231
7232 private:
7233 FactoryMap m_factories;
Phil Nashe73583d2015-08-07 17:30:34 +01007234 Listeners m_listeners;
Phil Nash3b80af72012-08-09 07:47:30 +01007235 };
7236}
7237
7238// #included from: catch_exception_translator_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007239#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01007240
7241#ifdef __OBJC__
7242#import "Foundation/Foundation.h"
7243#endif
7244
7245namespace Catch {
7246
7247 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
7248 public:
7249 ~ExceptionTranslatorRegistry() {
7250 deleteAll( m_translators );
7251 }
7252
7253 virtual void registerTranslator( const IExceptionTranslator* translator ) {
7254 m_translators.push_back( translator );
7255 }
7256
7257 virtual std::string translateActiveException() const {
7258 try {
7259#ifdef __OBJC__
7260 // In Objective-C try objective-c exceptions first
7261 @try {
Phil Nashe4fa62a2015-11-18 08:39:54 +00007262 return tryTranslators();
Phil Nash3b80af72012-08-09 07:47:30 +01007263 }
7264 @catch (NSException *exception) {
Phil Nash13f98432014-12-12 08:11:18 +00007265 return Catch::toString( [exception description] );
Phil Nash3b80af72012-08-09 07:47:30 +01007266 }
7267#else
Phil Nashe4fa62a2015-11-18 08:39:54 +00007268 return tryTranslators();
Phil Nash3b80af72012-08-09 07:47:30 +01007269#endif
7270 }
Phil Nashab036682014-06-02 07:48:03 +01007271 catch( TestFailureException& ) {
7272 throw;
7273 }
Phil Nash3b80af72012-08-09 07:47:30 +01007274 catch( std::exception& ex ) {
7275 return ex.what();
7276 }
7277 catch( std::string& msg ) {
7278 return msg;
7279 }
7280 catch( const char* msg ) {
7281 return msg;
7282 }
7283 catch(...) {
Phil Nashe4fa62a2015-11-18 08:39:54 +00007284 return "Unknown exception";
Phil Nash3b80af72012-08-09 07:47:30 +01007285 }
7286 }
7287
Phil Nashe4fa62a2015-11-18 08:39:54 +00007288 std::string tryTranslators() const {
7289 if( m_translators.empty() )
7290 throw;
7291 else
7292 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
Phil Nash3b80af72012-08-09 07:47:30 +01007293 }
7294
7295 private:
7296 std::vector<const IExceptionTranslator*> m_translators;
7297 };
7298}
7299
7300namespace Catch {
7301
7302 namespace {
7303
7304 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
7305
Phil Nash8defc712013-04-24 19:10:02 +01007306 RegistryHub( RegistryHub const& );
7307 void operator=( RegistryHub const& );
Phil Nash3b80af72012-08-09 07:47:30 +01007308
7309 public: // IRegistryHub
7310 RegistryHub() {
7311 }
Phil Nash19520152015-08-10 07:32:48 +01007312 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007313 return m_reporterRegistry;
7314 }
Phil Nash19520152015-08-10 07:32:48 +01007315 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007316 return m_testCaseRegistry;
7317 }
Phil Nash19520152015-08-10 07:32:48 +01007318 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007319 return m_exceptionTranslatorRegistry;
7320 }
7321
7322 public: // IMutableRegistryHub
Phil Nash19520152015-08-10 07:32:48 +01007323 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007324 m_reporterRegistry.registerReporter( name, factory );
7325 }
Phil Nash19520152015-08-10 07:32:48 +01007326 virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
Phil Nashe73583d2015-08-07 17:30:34 +01007327 m_reporterRegistry.registerListener( factory );
7328 }
Phil Nash19520152015-08-10 07:32:48 +01007329 virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007330 m_testCaseRegistry.registerTest( testInfo );
7331 }
Phil Nash19520152015-08-10 07:32:48 +01007332 virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007333 m_exceptionTranslatorRegistry.registerTranslator( translator );
7334 }
7335
7336 private:
7337 TestRegistry m_testCaseRegistry;
7338 ReporterRegistry m_reporterRegistry;
7339 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
7340 };
7341
7342 // Single, global, instance
7343 inline RegistryHub*& getTheRegistryHub() {
Phil Nashb971fe72015-07-02 08:21:38 +01007344 static RegistryHub* theRegistryHub = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007345 if( !theRegistryHub )
7346 theRegistryHub = new RegistryHub();
7347 return theRegistryHub;
7348 }
7349 }
7350
7351 IRegistryHub& getRegistryHub() {
7352 return *getTheRegistryHub();
7353 }
7354 IMutableRegistryHub& getMutableRegistryHub() {
7355 return *getTheRegistryHub();
7356 }
7357 void cleanUp() {
7358 delete getTheRegistryHub();
Phil Nashb971fe72015-07-02 08:21:38 +01007359 getTheRegistryHub() = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007360 cleanUpContext();
7361 }
Phil Nashce612bf2012-11-01 08:27:09 +00007362 std::string translateActiveException() {
7363 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
7364 }
Phil Nash3b80af72012-08-09 07:47:30 +01007365
7366} // end namespace Catch
Matt Wozniskif29c8982012-09-17 01:42:29 -04007367
Phil Nash3b80af72012-08-09 07:47:30 +01007368// #included from: catch_notimplemented_exception.hpp
7369#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
7370
Phil Nashd08cee22017-02-13 16:15:42 +00007371#include <sstream>
Phil Nash3b80af72012-08-09 07:47:30 +01007372
7373namespace Catch {
7374
Phil Nash8defc712013-04-24 19:10:02 +01007375 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
Phil Nash3b80af72012-08-09 07:47:30 +01007376 : m_lineInfo( lineInfo ) {
7377 std::ostringstream oss;
Phil Nash2e7d9662013-01-16 09:44:43 +00007378 oss << lineInfo << ": function ";
Phil Nash3b80af72012-08-09 07:47:30 +01007379 oss << "not implemented";
7380 m_what = oss.str();
7381 }
7382
Phil Nashd7e17902014-04-18 08:49:35 +01007383 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
Phil Nash3b80af72012-08-09 07:47:30 +01007384 return m_what.c_str();
7385 }
7386
7387} // end namespace Catch
7388
7389// #included from: catch_context_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007390#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01007391
Phil Nash3649fdf2013-12-03 18:53:55 +00007392// #included from: catch_stream.hpp
7393#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
7394
Phil Nash3649fdf2013-12-03 18:53:55 +00007395#include <stdexcept>
7396#include <cstdio>
Phil Nash383d7c02014-10-02 19:08:19 +01007397#include <iostream>
Phil Nash3649fdf2013-12-03 18:53:55 +00007398
7399namespace Catch {
7400
7401 template<typename WriterF, size_t bufferSize=256>
7402 class StreamBufImpl : public StreamBufBase {
7403 char data[bufferSize];
7404 WriterF m_writer;
7405
7406 public:
7407 StreamBufImpl() {
7408 setp( data, data + sizeof(data) );
7409 }
7410
Phil Nashd7e17902014-04-18 08:49:35 +01007411 ~StreamBufImpl() CATCH_NOEXCEPT {
Phil Nash3649fdf2013-12-03 18:53:55 +00007412 sync();
7413 }
7414
7415 private:
7416 int overflow( int c ) {
7417 sync();
7418
7419 if( c != EOF ) {
7420 if( pbase() == epptr() )
7421 m_writer( std::string( 1, static_cast<char>( c ) ) );
7422 else
7423 sputc( static_cast<char>( c ) );
7424 }
7425 return 0;
7426 }
7427
7428 int sync() {
7429 if( pbase() != pptr() ) {
7430 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
7431 setp( pbase(), epptr() );
7432 }
7433 return 0;
7434 }
7435 };
7436
7437 ///////////////////////////////////////////////////////////////////////////
7438
Phil Nash7e346192015-11-03 08:00:43 +00007439 FileStream::FileStream( std::string const& filename ) {
7440 m_ofs.open( filename.c_str() );
7441 if( m_ofs.fail() ) {
7442 std::ostringstream oss;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007443 oss << "Unable to open file: '" << filename << '\'';
Phil Nash7e346192015-11-03 08:00:43 +00007444 throw std::domain_error( oss.str() );
7445 }
7446 }
7447
7448 std::ostream& FileStream::stream() const {
7449 return m_ofs;
7450 }
7451
Phil Nash3649fdf2013-12-03 18:53:55 +00007452 struct OutputDebugWriter {
7453
7454 void operator()( std::string const&str ) {
7455 writeToDebugConsole( str );
7456 }
7457 };
7458
Phil Nash7e346192015-11-03 08:00:43 +00007459 DebugOutStream::DebugOutStream()
7460 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
7461 m_os( m_streamBuf.get() )
Phil Nash3649fdf2013-12-03 18:53:55 +00007462 {}
7463
Phil Nash7e346192015-11-03 08:00:43 +00007464 std::ostream& DebugOutStream::stream() const {
7465 return m_os;
Phil Nash3649fdf2013-12-03 18:53:55 +00007466 }
Phil Nash383d7c02014-10-02 19:08:19 +01007467
Phil Nash7e346192015-11-03 08:00:43 +00007468 // Store the streambuf from cout up-front because
7469 // cout may get redirected when running tests
7470 CoutStream::CoutStream()
7471 : m_os( Catch::cout().rdbuf() )
Phil Nash3649fdf2013-12-03 18:53:55 +00007472 {}
7473
Phil Nash7e346192015-11-03 08:00:43 +00007474 std::ostream& CoutStream::stream() const {
7475 return m_os;
Phil Nash3649fdf2013-12-03 18:53:55 +00007476 }
Phil Nash383d7c02014-10-02 19:08:19 +01007477
Phil Nashfdc42d02015-12-04 10:19:08 +00007478#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
Phil Nash383d7c02014-10-02 19:08:19 +01007479 std::ostream& cout() {
7480 return std::cout;
7481 }
7482 std::ostream& cerr() {
7483 return std::cerr;
7484 }
7485#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00007486}
7487
Phil Nash3b80af72012-08-09 07:47:30 +01007488namespace Catch {
7489
7490 class Context : public IMutableContext {
7491
Phil Nashb971fe72015-07-02 08:21:38 +01007492 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
Phil Nash8defc712013-04-24 19:10:02 +01007493 Context( Context const& );
7494 void operator=( Context const& );
Phil Nash3b80af72012-08-09 07:47:30 +01007495
Martin Hořeňovský9a566092017-01-20 12:49:59 +01007496 public:
7497 virtual ~Context() {
7498 deleteAllValues( m_generatorsByTestName );
7499 }
7500
Phil Nash3b80af72012-08-09 07:47:30 +01007501 public: // IContext
Phil Nash9241e432014-05-20 18:50:59 +01007502 virtual IResultCapture* getResultCapture() {
7503 return m_resultCapture;
Phil Nash3b80af72012-08-09 07:47:30 +01007504 }
Phil Nash9241e432014-05-20 18:50:59 +01007505 virtual IRunner* getRunner() {
7506 return m_runner;
Phil Nash3b80af72012-08-09 07:47:30 +01007507 }
Phil Nash8defc712013-04-24 19:10:02 +01007508 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007509 return getGeneratorsForCurrentTest()
7510 .getGeneratorInfo( fileInfo, totalSize )
7511 .getCurrentIndex();
7512 }
7513 virtual bool advanceGeneratorsForCurrentTest() {
7514 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7515 return generators && generators->moveNext();
7516 }
7517
Phil Nash786959d2013-06-07 19:07:50 +01007518 virtual Ptr<IConfig const> getConfig() const {
Phil Nash3b80af72012-08-09 07:47:30 +01007519 return m_config;
7520 }
7521
7522 public: // IMutableContext
7523 virtual void setResultCapture( IResultCapture* resultCapture ) {
7524 m_resultCapture = resultCapture;
7525 }
7526 virtual void setRunner( IRunner* runner ) {
7527 m_runner = runner;
7528 }
Phil Nash786959d2013-06-07 19:07:50 +01007529 virtual void setConfig( Ptr<IConfig const> const& config ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007530 m_config = config;
7531 }
7532
7533 friend IMutableContext& getCurrentMutableContext();
7534
7535 private:
7536 IGeneratorsForTest* findGeneratorsForCurrentTest() {
Phil Nash9241e432014-05-20 18:50:59 +01007537 std::string testName = getResultCapture()->getCurrentTestName();
Phil Nash3b80af72012-08-09 07:47:30 +01007538
7539 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
Phil Nasha806c3e2015-03-04 08:23:40 +00007540 m_generatorsByTestName.find( testName );
Phil Nash3b80af72012-08-09 07:47:30 +01007541 return it != m_generatorsByTestName.end()
Phil Nash8a52a392013-07-25 08:12:03 +01007542 ? it->second
Phil Nashb971fe72015-07-02 08:21:38 +01007543 : CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007544 }
7545
7546 IGeneratorsForTest& getGeneratorsForCurrentTest() {
7547 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7548 if( !generators ) {
Phil Nash9241e432014-05-20 18:50:59 +01007549 std::string testName = getResultCapture()->getCurrentTestName();
Phil Nash3b80af72012-08-09 07:47:30 +01007550 generators = createGeneratorsForTest();
7551 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
7552 }
7553 return *generators;
7554 }
7555
7556 private:
Phil Nash93a945c2013-10-23 15:35:07 +01007557 Ptr<IConfig const> m_config;
Phil Nash3b80af72012-08-09 07:47:30 +01007558 IRunner* m_runner;
7559 IResultCapture* m_resultCapture;
Phil Nash3b80af72012-08-09 07:47:30 +01007560 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
7561 };
7562
7563 namespace {
Phil Nashb971fe72015-07-02 08:21:38 +01007564 Context* currentContext = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007565 }
7566 IMutableContext& getCurrentMutableContext() {
7567 if( !currentContext )
7568 currentContext = new Context();
7569 return *currentContext;
7570 }
7571 IContext& getCurrentContext() {
7572 return getCurrentMutableContext();
7573 }
7574
Phil Nash3b80af72012-08-09 07:47:30 +01007575 void cleanUpContext() {
7576 delete currentContext;
Phil Nashb971fe72015-07-02 08:21:38 +01007577 currentContext = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007578 }
7579}
Matt Wozniskif29c8982012-09-17 01:42:29 -04007580
Phil Nash3b80af72012-08-09 07:47:30 +01007581// #included from: catch_console_colour_impl.hpp
7582#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
7583
Phil Nashe54ac702014-10-21 07:25:26 +01007584namespace Catch {
7585 namespace {
Phil Nash12c16ff2013-04-05 20:58:01 +01007586
Phil Nashe54ac702014-10-21 07:25:26 +01007587 struct IColourImpl {
7588 virtual ~IColourImpl() {}
7589 virtual void use( Colour::Code _colourCode ) = 0;
7590 };
7591
7592 struct NoColourImpl : IColourImpl {
7593 void use( Colour::Code ) {}
7594
7595 static IColourImpl* instance() {
7596 static NoColourImpl s_instance;
7597 return &s_instance;
7598 }
7599 };
7600
7601 } // anon namespace
7602} // namespace Catch
7603
7604#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
7605# ifdef CATCH_PLATFORM_WINDOWS
7606# define CATCH_CONFIG_COLOUR_WINDOWS
7607# else
7608# define CATCH_CONFIG_COLOUR_ANSI
7609# endif
7610#endif
7611
7612#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01007613
Phil Nash3b80af72012-08-09 07:47:30 +01007614namespace Catch {
Phil Nash3df6c0d2013-03-11 18:38:29 +00007615namespace {
Phil Nash3b80af72012-08-09 07:47:30 +01007616
Phil Nashe54ac702014-10-21 07:25:26 +01007617 class Win32ColourImpl : public IColourImpl {
Phil Nash3b80af72012-08-09 07:47:30 +01007618 public:
Phil Nash12c16ff2013-04-05 20:58:01 +01007619 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
Phil Nash3b80af72012-08-09 07:47:30 +01007620 {
Phil Nash12c16ff2013-04-05 20:58:01 +01007621 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
7622 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
Phil Nash584032d2015-07-06 06:22:28 +01007623 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
7624 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
Phil Nash3b80af72012-08-09 07:47:30 +01007625 }
Phil Nash3b80af72012-08-09 07:47:30 +01007626
Phil Nash12c16ff2013-04-05 20:58:01 +01007627 virtual void use( Colour::Code _colourCode ) {
7628 switch( _colourCode ) {
Phil Nash584032d2015-07-06 06:22:28 +01007629 case Colour::None: return setTextAttribute( originalForegroundAttributes );
Phil Nash12c16ff2013-04-05 20:58:01 +01007630 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7631 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
7632 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
7633 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
7634 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
7635 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
7636 case Colour::Grey: return setTextAttribute( 0 );
Phil Nash3b80af72012-08-09 07:47:30 +01007637
Phil Nash12c16ff2013-04-05 20:58:01 +01007638 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
7639 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
7640 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
Phil Nash23520432013-06-28 14:11:28 +01007641 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
Phil Nash3b80af72012-08-09 07:47:30 +01007642
Phil Nash12c16ff2013-04-05 20:58:01 +01007643 case Colour::Bright: throw std::logic_error( "not a colour" );
7644 }
Phil Nash3b80af72012-08-09 07:47:30 +01007645 }
Phil Nash3b80af72012-08-09 07:47:30 +01007646
7647 private:
Phil Nash12c16ff2013-04-05 20:58:01 +01007648 void setTextAttribute( WORD _textAttribute ) {
Phil Nash584032d2015-07-06 06:22:28 +01007649 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
Phil Nash3b80af72012-08-09 07:47:30 +01007650 }
Phil Nash12c16ff2013-04-05 20:58:01 +01007651 HANDLE stdoutHandle;
Phil Nash584032d2015-07-06 06:22:28 +01007652 WORD originalForegroundAttributes;
7653 WORD originalBackgroundAttributes;
Phil Nash3b80af72012-08-09 07:47:30 +01007654 };
7655
Phil Nashe54ac702014-10-21 07:25:26 +01007656 IColourImpl* platformColourInstance() {
Phil Nash20cad7c2014-04-15 18:44:37 +01007657 static Win32ColourImpl s_instance;
Phil Nashae5ee2c2016-02-29 08:17:18 +00007658
7659 Ptr<IConfig const> config = getCurrentContext().getConfig();
7660 UseColour::YesOrNo colourMode = config
7661 ? config->useColour()
7662 : UseColour::Auto;
7663 if( colourMode == UseColour::Auto )
7664 colourMode = !isDebuggerActive()
7665 ? UseColour::Yes
7666 : UseColour::No;
7667 return colourMode == UseColour::Yes
7668 ? &s_instance
7669 : NoColourImpl::instance();
Phil Nash20cad7c2014-04-15 18:44:37 +01007670 }
Phil Nash3df6c0d2013-03-11 18:38:29 +00007671
7672} // end anon namespace
Phil Nash3b80af72012-08-09 07:47:30 +01007673} // end namespace Catch
7674
Phil Nashe54ac702014-10-21 07:25:26 +01007675#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
Phil Nashce612bf2012-11-01 08:27:09 +00007676
7677#include <unistd.h>
7678
7679namespace Catch {
Phil Nash3df6c0d2013-03-11 18:38:29 +00007680namespace {
Phil Nashce612bf2012-11-01 08:27:09 +00007681
7682 // use POSIX/ ANSI console terminal codes
Phil Nash12c16ff2013-04-05 20:58:01 +01007683 // Thanks to Adam Strzelecki for original contribution
7684 // (http://github.com/nanoant)
Phil Nashce612bf2012-11-01 08:27:09 +00007685 // https://github.com/philsquared/Catch/pull/131
Phil Nashe54ac702014-10-21 07:25:26 +01007686 class PosixColourImpl : public IColourImpl {
Phil Nash12c16ff2013-04-05 20:58:01 +01007687 public:
7688 virtual void use( Colour::Code _colourCode ) {
7689 switch( _colourCode ) {
7690 case Colour::None:
7691 case Colour::White: return setColour( "[0m" );
7692 case Colour::Red: return setColour( "[0;31m" );
7693 case Colour::Green: return setColour( "[0;32m" );
Phil Nash3b2f2062017-01-11 16:43:56 +00007694 case Colour::Blue: return setColour( "[0;34m" );
Phil Nash12c16ff2013-04-05 20:58:01 +01007695 case Colour::Cyan: return setColour( "[0;36m" );
7696 case Colour::Yellow: return setColour( "[0;33m" );
7697 case Colour::Grey: return setColour( "[1;30m" );
Phil Nashce612bf2012-11-01 08:27:09 +00007698
Phil Nash12c16ff2013-04-05 20:58:01 +01007699 case Colour::LightGrey: return setColour( "[0;37m" );
7700 case Colour::BrightRed: return setColour( "[1;31m" );
Phil Nash243f2d22013-04-12 10:43:06 +01007701 case Colour::BrightGreen: return setColour( "[1;32m" );
Phil Nash12c16ff2013-04-05 20:58:01 +01007702 case Colour::BrightWhite: return setColour( "[1;37m" );
Phil Nashce612bf2012-11-01 08:27:09 +00007703
Phil Nash12c16ff2013-04-05 20:58:01 +01007704 case Colour::Bright: throw std::logic_error( "not a colour" );
Phil Nashce612bf2012-11-01 08:27:09 +00007705 }
7706 }
Phil Nashe54ac702014-10-21 07:25:26 +01007707 static IColourImpl* instance() {
7708 static PosixColourImpl s_instance;
7709 return &s_instance;
7710 }
7711
Phil Nash12c16ff2013-04-05 20:58:01 +01007712 private:
7713 void setColour( const char* _escapeCode ) {
Phil Nash383d7c02014-10-02 19:08:19 +01007714 Catch::cout() << '\033' << _escapeCode;
Phil Nash3df6c0d2013-03-11 18:38:29 +00007715 }
7716 };
7717
Phil Nashe54ac702014-10-21 07:25:26 +01007718 IColourImpl* platformColourInstance() {
Phil Nasha806c3e2015-03-04 08:23:40 +00007719 Ptr<IConfig const> config = getCurrentContext().getConfig();
Phil Nashae5ee2c2016-02-29 08:17:18 +00007720 UseColour::YesOrNo colourMode = config
7721 ? config->useColour()
7722 : UseColour::Auto;
7723 if( colourMode == UseColour::Auto )
7724 colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
7725 ? UseColour::Yes
7726 : UseColour::No;
7727 return colourMode == UseColour::Yes
Phil Nashe54ac702014-10-21 07:25:26 +01007728 ? PosixColourImpl::instance()
7729 : NoColourImpl::instance();
Phil Nash20cad7c2014-04-15 18:44:37 +01007730 }
Phil Nashce612bf2012-11-01 08:27:09 +00007731
Phil Nash12c16ff2013-04-05 20:58:01 +01007732} // end anon namespace
7733} // end namespace Catch
Phil Nash3b80af72012-08-09 07:47:30 +01007734
Phil Nashe54ac702014-10-21 07:25:26 +01007735#else // not Windows or ANSI ///////////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01007736
7737namespace Catch {
7738
Phil Nashe54ac702014-10-21 07:25:26 +01007739 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
Phil Nash20cad7c2014-04-15 18:44:37 +01007740
Phil Nashe54ac702014-10-21 07:25:26 +01007741} // end namespace Catch
7742
7743#endif // Windows/ ANSI/ None
7744
7745namespace Catch {
Phil Nash3b80af72012-08-09 07:47:30 +01007746
Phil Nashce562092014-07-09 07:40:37 +01007747 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
7748 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
7749 Colour::~Colour(){ if( !m_moved ) use( None ); }
Phil Nash3b80af72012-08-09 07:47:30 +01007750
Phil Nashe54ac702014-10-21 07:25:26 +01007751 void Colour::use( Code _colourCode ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00007752 static IColourImpl* impl = platformColourInstance();
Phil Nashe54ac702014-10-21 07:25:26 +01007753 impl->use( _colourCode );
Phil Nash20cad7c2014-04-15 18:44:37 +01007754 }
Phil Nash3b80af72012-08-09 07:47:30 +01007755
7756} // end namespace Catch
7757
Phil Nash3b80af72012-08-09 07:47:30 +01007758// #included from: catch_generators_impl.hpp
7759#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
7760
7761#include <vector>
7762#include <string>
7763#include <map>
7764
7765namespace Catch {
7766
7767 struct GeneratorInfo : IGeneratorInfo {
7768
7769 GeneratorInfo( std::size_t size )
7770 : m_size( size ),
7771 m_currentIndex( 0 )
7772 {}
7773
7774 bool moveNext() {
7775 if( ++m_currentIndex == m_size ) {
7776 m_currentIndex = 0;
7777 return false;
7778 }
7779 return true;
7780 }
7781
7782 std::size_t getCurrentIndex() const {
7783 return m_currentIndex;
7784 }
7785
7786 std::size_t m_size;
7787 std::size_t m_currentIndex;
7788 };
7789
7790 ///////////////////////////////////////////////////////////////////////////
7791
7792 class GeneratorsForTest : public IGeneratorsForTest {
7793
7794 public:
7795 ~GeneratorsForTest() {
7796 deleteAll( m_generatorsInOrder );
7797 }
7798
Phil Nash8defc712013-04-24 19:10:02 +01007799 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007800 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
7801 if( it == m_generatorsByName.end() ) {
7802 IGeneratorInfo* info = new GeneratorInfo( size );
7803 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
7804 m_generatorsInOrder.push_back( info );
7805 return *info;
7806 }
7807 return *it->second;
7808 }
7809
7810 bool moveNext() {
7811 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
7812 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
7813 for(; it != itEnd; ++it ) {
7814 if( (*it)->moveNext() )
7815 return true;
7816 }
7817 return false;
7818 }
7819
7820 private:
7821 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
7822 std::vector<IGeneratorInfo*> m_generatorsInOrder;
7823 };
7824
7825 IGeneratorsForTest* createGeneratorsForTest()
7826 {
7827 return new GeneratorsForTest();
7828 }
7829
7830} // end namespace Catch
7831
Phil Nashce612bf2012-11-01 08:27:09 +00007832// #included from: catch_assertionresult.hpp
7833#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01007834
7835namespace Catch {
7836
Phil Nash8defc712013-04-24 19:10:02 +01007837 AssertionInfo::AssertionInfo( std::string const& _macroName,
7838 SourceLineInfo const& _lineInfo,
7839 std::string const& _capturedExpression,
Phil Nash90a35942012-11-13 22:04:29 +00007840 ResultDisposition::Flags _resultDisposition )
7841 : macroName( _macroName ),
7842 lineInfo( _lineInfo ),
7843 capturedExpression( _capturedExpression ),
7844 resultDisposition( _resultDisposition )
Phil Nash786959d2013-06-07 19:07:50 +01007845 {}
Phil Nash90a35942012-11-13 22:04:29 +00007846
Phil Nashce612bf2012-11-01 08:27:09 +00007847 AssertionResult::AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01007848
Phil Nash8defc712013-04-24 19:10:02 +01007849 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
Phil Nashce612bf2012-11-01 08:27:09 +00007850 : m_info( info ),
7851 m_resultData( data )
7852 {}
Phil Nash3b80af72012-08-09 07:47:30 +01007853
Phil Nashce612bf2012-11-01 08:27:09 +00007854 AssertionResult::~AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01007855
Phil Nash90a35942012-11-13 22:04:29 +00007856 // Result was a success
7857 bool AssertionResult::succeeded() const {
7858 return Catch::isOk( m_resultData.resultType );
7859 }
7860
7861 // Result was a success, or failure is suppressed
7862 bool AssertionResult::isOk() const {
7863 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
Phil Nash3b80af72012-08-09 07:47:30 +01007864 }
7865
Phil Nashce612bf2012-11-01 08:27:09 +00007866 ResultWas::OfType AssertionResult::getResultType() const {
7867 return m_resultData.resultType;
Phil Nash3b80af72012-08-09 07:47:30 +01007868 }
7869
Phil Nashce612bf2012-11-01 08:27:09 +00007870 bool AssertionResult::hasExpression() const {
7871 return !m_info.capturedExpression.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01007872 }
7873
Phil Nashce612bf2012-11-01 08:27:09 +00007874 bool AssertionResult::hasMessage() const {
7875 return !m_resultData.message.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01007876 }
7877
Phil Nashce612bf2012-11-01 08:27:09 +00007878 std::string AssertionResult::getExpression() const {
Phil Nashab036682014-06-02 07:48:03 +01007879 if( isFalseTest( m_info.resultDisposition ) )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007880 return '!' + m_info.capturedExpression;
Phil Nash786959d2013-06-07 19:07:50 +01007881 else
7882 return m_info.capturedExpression;
7883 }
7884 std::string AssertionResult::getExpressionInMacro() const {
7885 if( m_info.macroName.empty() )
7886 return m_info.capturedExpression;
7887 else
7888 return m_info.macroName + "( " + m_info.capturedExpression + " )";
Phil Nash3b80af72012-08-09 07:47:30 +01007889 }
7890
Phil Nashce612bf2012-11-01 08:27:09 +00007891 bool AssertionResult::hasExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01007892 return hasExpression() && getExpandedExpression() != getExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01007893 }
7894
Phil Nashce612bf2012-11-01 08:27:09 +00007895 std::string AssertionResult::getExpandedExpression() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007896 return m_resultData.reconstructExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01007897 }
7898
Phil Nashce612bf2012-11-01 08:27:09 +00007899 std::string AssertionResult::getMessage() const {
7900 return m_resultData.message;
7901 }
7902 SourceLineInfo AssertionResult::getSourceInfo() const {
7903 return m_info.lineInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01007904 }
7905
Phil Nashce612bf2012-11-01 08:27:09 +00007906 std::string AssertionResult::getTestMacroName() const {
7907 return m_info.macroName;
Phil Nash3b80af72012-08-09 07:47:30 +01007908 }
7909
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007910 void AssertionResult::discardDecomposedExpression() const {
7911 m_resultData.decomposedExpression = CATCH_NULL;
7912 }
7913
7914 void AssertionResult::expandDecomposedExpression() const {
7915 m_resultData.reconstructExpression();
7916 }
7917
Phil Nash3b80af72012-08-09 07:47:30 +01007918} // end namespace Catch
7919
Phil Nash5bc030d2012-08-16 18:48:50 +01007920// #included from: catch_test_case_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007921#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
Phil Nash5bc030d2012-08-16 18:48:50 +01007922
Phil Nashd08cee22017-02-13 16:15:42 +00007923#include <cctype>
7924
Phil Nash5bc030d2012-08-16 18:48:50 +01007925namespace Catch {
7926
Phil Nash52e1e742014-07-03 08:11:38 +01007927 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007928 if( startsWith( tag, '.' ) ||
Phil Nash52e1e742014-07-03 08:11:38 +01007929 tag == "hide" ||
7930 tag == "!hide" )
7931 return TestCaseInfo::IsHidden;
7932 else if( tag == "!throws" )
7933 return TestCaseInfo::Throws;
7934 else if( tag == "!shouldfail" )
7935 return TestCaseInfo::ShouldFail;
7936 else if( tag == "!mayfail" )
7937 return TestCaseInfo::MayFail;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007938 else if( tag == "!nonportable" )
7939 return TestCaseInfo::NonPortable;
Phil Nash52e1e742014-07-03 08:11:38 +01007940 else
7941 return TestCaseInfo::None;
Phil Nash20cad7c2014-04-15 18:44:37 +01007942 }
7943 inline bool isReservedTag( std::string const& tag ) {
Phil Nashd08cee22017-02-13 16:15:42 +00007944 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
Phil Nash20cad7c2014-04-15 18:44:37 +01007945 }
Phil Nash65cc14c2014-05-16 18:54:48 +01007946 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
7947 if( isReservedTag( tag ) ) {
7948 {
7949 Colour colourGuard( Colour::Red );
Phil Nash383d7c02014-10-02 19:08:19 +01007950 Catch::cerr()
Phil Nash65cc14c2014-05-16 18:54:48 +01007951 << "Tag name [" << tag << "] not allowed.\n"
7952 << "Tag names starting with non alpha-numeric characters are reserved\n";
7953 }
7954 {
7955 Colour colourGuard( Colour::FileName );
Phil Nash383d7c02014-10-02 19:08:19 +01007956 Catch::cerr() << _lineInfo << std::endl;
Phil Nash65cc14c2014-05-16 18:54:48 +01007957 }
7958 exit(1);
7959 }
7960 }
Phil Nash20cad7c2014-04-15 18:44:37 +01007961
Phil Nasha1fbfea2012-12-01 23:57:18 +00007962 TestCase makeTestCase( ITestCase* _testCase,
Phil Nash8defc712013-04-24 19:10:02 +01007963 std::string const& _className,
7964 std::string const& _name,
7965 std::string const& _descOrTags,
7966 SourceLineInfo const& _lineInfo )
Phil Nashfc1baac2012-09-15 17:53:27 +01007967 {
Phil Nash5ecb72b2013-11-26 20:57:45 +00007968 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
Phil Nash65cc14c2014-05-16 18:54:48 +01007969
7970 // Parse out tags
Phil Nasha1fbfea2012-12-01 23:57:18 +00007971 std::set<std::string> tags;
Phil Nash65cc14c2014-05-16 18:54:48 +01007972 std::string desc, tag;
7973 bool inTag = false;
7974 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
7975 char c = _descOrTags[i];
7976 if( !inTag ) {
7977 if( c == '[' )
7978 inTag = true;
7979 else
7980 desc += c;
Phil Nash20cad7c2014-04-15 18:44:37 +01007981 }
Phil Nash65cc14c2014-05-16 18:54:48 +01007982 else {
7983 if( c == ']' ) {
Phil Nash91c17f32014-12-15 07:26:31 +00007984 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
7985 if( prop == TestCaseInfo::IsHidden )
Phil Nashebd48882014-05-19 18:22:59 +01007986 isHidden = true;
Phil Nash91c17f32014-12-15 07:26:31 +00007987 else if( prop == TestCaseInfo::None )
7988 enforceNotReservedTag( tag, _lineInfo );
7989
7990 tags.insert( tag );
Phil Nash65cc14c2014-05-16 18:54:48 +01007991 tag.clear();
Phil Nash91c17f32014-12-15 07:26:31 +00007992 inTag = false;
Phil Nash65cc14c2014-05-16 18:54:48 +01007993 }
7994 else
7995 tag += c;
7996 }
Phil Nashde49ec42013-12-04 20:25:14 +00007997 }
Phil Nash9241e432014-05-20 18:50:59 +01007998 if( isHidden ) {
7999 tags.insert( "hide" );
8000 tags.insert( "." );
8001 }
8002
Phil Nash52e1e742014-07-03 08:11:38 +01008003 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
Phil Nasha1fbfea2012-12-01 23:57:18 +00008004 return TestCase( _testCase, info );
Phil Nashfc1baac2012-09-15 17:53:27 +01008005 }
Phil Nash5bc030d2012-08-16 18:48:50 +01008006
Phil Nashb971fe72015-07-02 08:21:38 +01008007 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
8008 {
8009 testCaseInfo.tags = tags;
8010 testCaseInfo.lcaseTags.clear();
8011
8012 std::ostringstream oss;
8013 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 +01008014 oss << '[' << *it << ']';
Phil Nashb971fe72015-07-02 08:21:38 +01008015 std::string lcaseTag = toLower( *it );
8016 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
8017 testCaseInfo.lcaseTags.insert( lcaseTag );
8018 }
8019 testCaseInfo.tagsAsString = oss.str();
8020 }
8021
Phil Nash8defc712013-04-24 19:10:02 +01008022 TestCaseInfo::TestCaseInfo( std::string const& _name,
8023 std::string const& _className,
8024 std::string const& _description,
8025 std::set<std::string> const& _tags,
Phil Nash8defc712013-04-24 19:10:02 +01008026 SourceLineInfo const& _lineInfo )
Phil Nasha1fbfea2012-12-01 23:57:18 +00008027 : name( _name ),
8028 className( _className ),
8029 description( _description ),
Phil Nashff03cdf2012-12-06 08:44:51 +00008030 lineInfo( _lineInfo ),
Phil Nash52e1e742014-07-03 08:11:38 +01008031 properties( None )
Phil Nash38f7eef2013-03-29 13:44:33 +00008032 {
Phil Nashb971fe72015-07-02 08:21:38 +01008033 setTags( *this, _tags );
Phil Nash38f7eef2013-03-29 13:44:33 +00008034 }
Phil Nash5bc030d2012-08-16 18:48:50 +01008035
Phil Nash8defc712013-04-24 19:10:02 +01008036 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00008037 : name( other.name ),
8038 className( other.className ),
8039 description( other.description ),
8040 tags( other.tags ),
Phil Nash9241e432014-05-20 18:50:59 +01008041 lcaseTags( other.lcaseTags ),
Phil Nash38f7eef2013-03-29 13:44:33 +00008042 tagsAsString( other.tagsAsString ),
Phil Nashff03cdf2012-12-06 08:44:51 +00008043 lineInfo( other.lineInfo ),
Phil Nash52e1e742014-07-03 08:11:38 +01008044 properties( other.properties )
Phil Nash5bc030d2012-08-16 18:48:50 +01008045 {}
8046
Phil Nash52e1e742014-07-03 08:11:38 +01008047 bool TestCaseInfo::isHidden() const {
8048 return ( properties & IsHidden ) != 0;
8049 }
8050 bool TestCaseInfo::throws() const {
8051 return ( properties & Throws ) != 0;
8052 }
8053 bool TestCaseInfo::okToFail() const {
8054 return ( properties & (ShouldFail | MayFail ) ) != 0;
8055 }
8056 bool TestCaseInfo::expectedToFail() const {
8057 return ( properties & (ShouldFail ) ) != 0;
8058 }
8059
Phil Nash8defc712013-04-24 19:10:02 +01008060 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00008061
Phil Nash8defc712013-04-24 19:10:02 +01008062 TestCase::TestCase( TestCase const& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00008063 : TestCaseInfo( other ),
8064 test( other.test )
Phil Nash5bc030d2012-08-16 18:48:50 +01008065 {}
8066
Phil Nash8defc712013-04-24 19:10:02 +01008067 TestCase TestCase::withName( std::string const& _newName ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00008068 TestCase other( *this );
8069 other.name = _newName;
8070 return other;
Phil Nash5bc030d2012-08-16 18:48:50 +01008071 }
8072
Phil Nash9241e432014-05-20 18:50:59 +01008073 void TestCase::swap( TestCase& other ) {
8074 test.swap( other.test );
8075 name.swap( other.name );
8076 className.swap( other.className );
8077 description.swap( other.description );
8078 tags.swap( other.tags );
8079 lcaseTags.swap( other.lcaseTags );
8080 tagsAsString.swap( other.tagsAsString );
Phil Nash52e1e742014-07-03 08:11:38 +01008081 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
Phil Nash9241e432014-05-20 18:50:59 +01008082 std::swap( lineInfo, other.lineInfo );
8083 }
8084
Phil Nasha1fbfea2012-12-01 23:57:18 +00008085 void TestCase::invoke() const {
8086 test->invoke();
Phil Nash5bc030d2012-08-16 18:48:50 +01008087 }
8088
Phil Nash8defc712013-04-24 19:10:02 +01008089 bool TestCase::operator == ( TestCase const& other ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00008090 return test.get() == other.test.get() &&
8091 name == other.name &&
8092 className == other.className;
Phil Nash5bc030d2012-08-16 18:48:50 +01008093 }
8094
Phil Nash8defc712013-04-24 19:10:02 +01008095 bool TestCase::operator < ( TestCase const& other ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00008096 return name < other.name;
Phil Nash5bc030d2012-08-16 18:48:50 +01008097 }
Phil Nash8defc712013-04-24 19:10:02 +01008098 TestCase& TestCase::operator = ( TestCase const& other ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00008099 TestCase temp( other );
Phil Nashd2ec8492012-08-23 19:48:57 +01008100 swap( temp );
8101 return *this;
8102 }
Phil Nash799ecf92012-09-24 08:30:13 +01008103
Phil Nash8defc712013-04-24 19:10:02 +01008104 TestCaseInfo const& TestCase::getTestCaseInfo() const
Phil Nasha1fbfea2012-12-01 23:57:18 +00008105 {
8106 return *this;
8107 }
8108
Phil Nash799ecf92012-09-24 08:30:13 +01008109} // end namespace Catch
Phil Nash5bc030d2012-08-16 18:48:50 +01008110
Phil Nash7673a302012-11-15 22:15:41 +00008111// #included from: catch_version.hpp
8112#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
8113
8114namespace Catch {
8115
Phil Nash21f7ef62015-06-29 18:05:23 +01008116 Version::Version
8117 ( unsigned int _majorVersion,
8118 unsigned int _minorVersion,
8119 unsigned int _patchNumber,
8120 std::string const& _branchName,
8121 unsigned int _buildNumber )
8122 : majorVersion( _majorVersion ),
8123 minorVersion( _minorVersion ),
8124 patchNumber( _patchNumber ),
8125 branchName( _branchName ),
8126 buildNumber( _buildNumber )
8127 {}
8128
8129 std::ostream& operator << ( std::ostream& os, Version const& version ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008130 os << version.majorVersion << '.'
8131 << version.minorVersion << '.'
Phil Nash21f7ef62015-06-29 18:05:23 +01008132 << version.patchNumber;
8133
8134 if( !version.branchName.empty() ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008135 os << '-' << version.branchName
8136 << '.' << version.buildNumber;
Phil Nash21f7ef62015-06-29 18:05:23 +01008137 }
8138 return os;
8139 }
8140
Phil Nashc6535a02017-03-01 16:04:44 +00008141 Version libraryVersion( 1, 8, 1, "", 0 );
Phil Nash21f7ef62015-06-29 18:05:23 +01008142
Phil Nash7673a302012-11-15 22:15:41 +00008143}
8144
Phil Nasha2773812013-02-02 20:37:58 +00008145// #included from: catch_message.hpp
8146#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
8147
8148namespace Catch {
8149
8150 MessageInfo::MessageInfo( std::string const& _macroName,
8151 SourceLineInfo const& _lineInfo,
8152 ResultWas::OfType _type )
8153 : macroName( _macroName ),
8154 lineInfo( _lineInfo ),
8155 type( _type ),
8156 sequence( ++globalCount )
8157 {}
8158
8159 // This may need protecting if threading support is added
8160 unsigned int MessageInfo::globalCount = 0;
8161
8162 ////////////////////////////////////////////////////////////////////////////
8163
Phil Nashb5fd5a62013-06-28 17:09:57 +01008164 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
8165 : m_info( builder.m_info )
8166 {
8167 m_info.message = builder.m_stream.str();
8168 getResultCapture().pushScopedMessage( m_info );
Phil Nasha2773812013-02-02 20:37:58 +00008169 }
Phil Nash9241e432014-05-20 18:50:59 +01008170 ScopedMessage::ScopedMessage( ScopedMessage const& other )
8171 : m_info( other.m_info )
8172 {}
8173
Phil Nashb5fd5a62013-06-28 17:09:57 +01008174 ScopedMessage::~ScopedMessage() {
8175 getResultCapture().popScopedMessage( m_info );
Phil Nasha2773812013-02-02 20:37:58 +00008176 }
8177
8178} // end namespace Catch
8179
Phil Nash243f2d22013-04-12 10:43:06 +01008180// #included from: catch_legacy_reporter_adapter.hpp
Phil Nash87641772013-04-08 11:50:41 +01008181#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
8182
8183// #included from: catch_legacy_reporter_adapter.h
8184#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
8185
8186namespace Catch
8187{
Phil Nash3649fdf2013-12-03 18:53:55 +00008188 // Deprecated
8189 struct IReporter : IShared {
8190 virtual ~IReporter();
8191
8192 virtual bool shouldRedirectStdout() const = 0;
8193
8194 virtual void StartTesting() = 0;
8195 virtual void EndTesting( Totals const& totals ) = 0;
8196 virtual void StartGroup( std::string const& groupName ) = 0;
8197 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
8198 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
8199 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
8200 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
8201 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
8202 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
8203 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
8204 virtual void Aborted() = 0;
8205 virtual void Result( AssertionResult const& result ) = 0;
8206 };
8207
Phil Nash87641772013-04-08 11:50:41 +01008208 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
8209 {
8210 public:
Phil Nash786959d2013-06-07 19:07:50 +01008211 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
Phil Nash87641772013-04-08 11:50:41 +01008212 virtual ~LegacyReporterAdapter();
8213
8214 virtual ReporterPreferences getPreferences() const;
8215 virtual void noMatchingTestCases( std::string const& );
8216 virtual void testRunStarting( TestRunInfo const& );
8217 virtual void testGroupStarting( GroupInfo const& groupInfo );
8218 virtual void testCaseStarting( TestCaseInfo const& testInfo );
8219 virtual void sectionStarting( SectionInfo const& sectionInfo );
8220 virtual void assertionStarting( AssertionInfo const& );
Phil Nashb5fd5a62013-06-28 17:09:57 +01008221 virtual bool assertionEnded( AssertionStats const& assertionStats );
Phil Nash87641772013-04-08 11:50:41 +01008222 virtual void sectionEnded( SectionStats const& sectionStats );
8223 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
8224 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
8225 virtual void testRunEnded( TestRunStats const& testRunStats );
Phil Nash92f08362014-12-22 20:18:05 +00008226 virtual void skipTest( TestCaseInfo const& );
Phil Nash87641772013-04-08 11:50:41 +01008227
8228 private:
8229 Ptr<IReporter> m_legacyReporter;
Phil Nash87641772013-04-08 11:50:41 +01008230 };
8231}
8232
8233namespace Catch
8234{
Phil Nash786959d2013-06-07 19:07:50 +01008235 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
8236 : m_legacyReporter( legacyReporter )
Phil Nash87641772013-04-08 11:50:41 +01008237 {}
8238 LegacyReporterAdapter::~LegacyReporterAdapter() {}
8239
8240 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
8241 ReporterPreferences prefs;
8242 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
8243 return prefs;
8244 }
8245
8246 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
8247 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
8248 m_legacyReporter->StartTesting();
8249 }
8250 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
8251 m_legacyReporter->StartGroup( groupInfo.name );
8252 }
8253 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
8254 m_legacyReporter->StartTestCase( testInfo );
8255 }
8256 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
8257 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
8258 }
8259 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
8260 // Not on legacy interface
8261 }
8262
Phil Nashb5fd5a62013-06-28 17:09:57 +01008263 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
Phil Nash87641772013-04-08 11:50:41 +01008264 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
8265 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
8266 it != itEnd;
8267 ++it ) {
8268 if( it->type == ResultWas::Info ) {
Phil Nashab036682014-06-02 07:48:03 +01008269 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
8270 rb << it->message;
8271 rb.setResultType( ResultWas::Info );
8272 AssertionResult result = rb.build();
Phil Nash87641772013-04-08 11:50:41 +01008273 m_legacyReporter->Result( result );
8274 }
8275 }
8276 }
8277 m_legacyReporter->Result( assertionStats.assertionResult );
Phil Nashb5fd5a62013-06-28 17:09:57 +01008278 return true;
Phil Nash87641772013-04-08 11:50:41 +01008279 }
8280 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
8281 if( sectionStats.missingAssertions )
8282 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
8283 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
8284 }
8285 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
Phil Nash87641772013-04-08 11:50:41 +01008286 m_legacyReporter->EndTestCase
8287 ( testCaseStats.testInfo,
8288 testCaseStats.totals,
8289 testCaseStats.stdOut,
8290 testCaseStats.stdErr );
8291 }
8292 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
8293 if( testGroupStats.aborting )
8294 m_legacyReporter->Aborted();
8295 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
8296 }
8297 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
8298 m_legacyReporter->EndTesting( testRunStats.totals );
8299 }
Phil Nash92f08362014-12-22 20:18:05 +00008300 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
8301 }
Phil Nash87641772013-04-08 11:50:41 +01008302}
8303
Phil Nashaa7123b2013-08-15 19:01:00 +01008304// #included from: catch_timer.hpp
8305
8306#ifdef __clang__
8307#pragma clang diagnostic push
8308#pragma clang diagnostic ignored "-Wc++11-long-long"
8309#endif
8310
Phil Nash04a33642013-08-16 19:09:09 +01008311#ifdef CATCH_PLATFORM_WINDOWS
Phil Nash0952b762017-02-28 14:19:09 +00008312
Phil Nashaa7123b2013-08-15 19:01:00 +01008313#else
Phil Nash0952b762017-02-28 14:19:09 +00008314
Phil Nashaa7123b2013-08-15 19:01:00 +01008315#include <sys/time.h>
Phil Nashc6535a02017-03-01 16:04:44 +00008316
Phil Nashaa7123b2013-08-15 19:01:00 +01008317#endif
8318
8319namespace Catch {
8320
8321 namespace {
Phil Nash04a33642013-08-16 19:09:09 +01008322#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01008323 uint64_t getCurrentTicks() {
8324 static uint64_t hz=0, hzo=0;
8325 if (!hz) {
Phil Nash37e55612015-03-27 18:02:28 +00008326 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
8327 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
Phil Nashaa7123b2013-08-15 19:01:00 +01008328 }
8329 uint64_t t;
Phil Nash37e55612015-03-27 18:02:28 +00008330 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
Phil Nashaa7123b2013-08-15 19:01:00 +01008331 return ((t-hzo)*1000000)/hz;
8332 }
8333#else
8334 uint64_t getCurrentTicks() {
8335 timeval t;
Phil Nashb971fe72015-07-02 08:21:38 +01008336 gettimeofday(&t,CATCH_NULL);
Phil Nashce562092014-07-09 07:40:37 +01008337 return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
Phil Nashaa7123b2013-08-15 19:01:00 +01008338 }
8339#endif
8340 }
8341
8342 void Timer::start() {
8343 m_ticks = getCurrentTicks();
8344 }
Phil Nash4caabfa2014-09-03 19:23:22 +01008345 unsigned int Timer::getElapsedMicroseconds() const {
Phil Nashce562092014-07-09 07:40:37 +01008346 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
Phil Nashaa7123b2013-08-15 19:01:00 +01008347 }
8348 unsigned int Timer::getElapsedMilliseconds() const {
Phil Nash4caabfa2014-09-03 19:23:22 +01008349 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
Phil Nashaa7123b2013-08-15 19:01:00 +01008350 }
8351 double Timer::getElapsedSeconds() const {
Phil Nash4caabfa2014-09-03 19:23:22 +01008352 return getElapsedMicroseconds()/1000000.0;
Phil Nashaa7123b2013-08-15 19:01:00 +01008353 }
8354
8355} // namespace Catch
8356
8357#ifdef __clang__
8358#pragma clang diagnostic pop
8359#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00008360// #included from: catch_common.hpp
8361#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
8362
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008363#include <cstring>
Phil Nashd08cee22017-02-13 16:15:42 +00008364#include <cctype>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008365
Phil Nash3649fdf2013-12-03 18:53:55 +00008366namespace Catch {
8367
8368 bool startsWith( std::string const& s, std::string const& prefix ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008369 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
8370 }
8371 bool startsWith( std::string const& s, char prefix ) {
8372 return !s.empty() && s[0] == prefix;
Phil Nash3649fdf2013-12-03 18:53:55 +00008373 }
8374 bool endsWith( std::string const& s, std::string const& suffix ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008375 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
8376 }
8377 bool endsWith( std::string const& s, char suffix ) {
8378 return !s.empty() && s[s.size()-1] == suffix;
Phil Nash3649fdf2013-12-03 18:53:55 +00008379 }
8380 bool contains( std::string const& s, std::string const& infix ) {
8381 return s.find( infix ) != std::string::npos;
8382 }
Phil Nashe27c4ee2016-10-26 12:08:26 +01008383 char toLowerCh(char c) {
Phil Nashd08cee22017-02-13 16:15:42 +00008384 return static_cast<char>( std::tolower( c ) );
Phil Nashe27c4ee2016-10-26 12:08:26 +01008385 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008386 void toLowerInPlace( std::string& s ) {
Phil Nashe27c4ee2016-10-26 12:08:26 +01008387 std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
Phil Nash3649fdf2013-12-03 18:53:55 +00008388 }
8389 std::string toLower( std::string const& s ) {
8390 std::string lc = s;
8391 toLowerInPlace( lc );
8392 return lc;
8393 }
8394 std::string trim( std::string const& str ) {
8395 static char const* whitespaceChars = "\n\r\t ";
8396 std::string::size_type start = str.find_first_not_of( whitespaceChars );
8397 std::string::size_type end = str.find_last_not_of( whitespaceChars );
8398
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008399 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
Phil Nash3649fdf2013-12-03 18:53:55 +00008400 }
8401
Phil Nash576aff62014-12-21 00:21:23 +00008402 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
8403 bool replaced = false;
8404 std::size_t i = str.find( replaceThis );
8405 while( i != std::string::npos ) {
8406 replaced = true;
8407 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
8408 if( i < str.size()-withThis.size() )
8409 i = str.find( replaceThis, i+withThis.size() );
8410 else
8411 i = std::string::npos;
8412 }
8413 return replaced;
8414 }
8415
Phil Nash3649fdf2013-12-03 18:53:55 +00008416 pluralise::pluralise( std::size_t count, std::string const& label )
8417 : m_count( count ),
8418 m_label( label )
8419 {}
8420
8421 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008422 os << pluraliser.m_count << ' ' << pluraliser.m_label;
Phil Nash3649fdf2013-12-03 18:53:55 +00008423 if( pluraliser.m_count != 1 )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008424 os << 's';
Phil Nash3649fdf2013-12-03 18:53:55 +00008425 return os;
8426 }
8427
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008428 SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){}
Phil Nashde49ec42013-12-04 20:25:14 +00008429 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
Phil Nash3649fdf2013-12-03 18:53:55 +00008430 : file( _file ),
8431 line( _line )
8432 {}
Phil Nash3649fdf2013-12-03 18:53:55 +00008433 bool SourceLineInfo::empty() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008434 return file[0] == '\0';
Phil Nash3649fdf2013-12-03 18:53:55 +00008435 }
8436 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008437 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
Phil Nash3649fdf2013-12-03 18:53:55 +00008438 }
Phil Nasha806c3e2015-03-04 08:23:40 +00008439 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008440 return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
Phil Nasha806c3e2015-03-04 08:23:40 +00008441 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008442
Phil Nash8f66e342015-07-02 23:03:13 +01008443 void seedRng( IConfig const& config ) {
8444 if( config.rngSeed() != 0 )
8445 std::srand( config.rngSeed() );
8446 }
8447 unsigned int rngSeed() {
8448 return getCurrentContext().getConfig()->rngSeed();
8449 }
8450
Phil Nash3649fdf2013-12-03 18:53:55 +00008451 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
8452#ifndef __GNUG__
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008453 os << info.file << '(' << info.line << ')';
Phil Nash3649fdf2013-12-03 18:53:55 +00008454#else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008455 os << info.file << ':' << info.line;
Phil Nash3649fdf2013-12-03 18:53:55 +00008456#endif
8457 return os;
8458 }
8459
8460 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
8461 std::ostringstream oss;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008462 oss << locationInfo << ": Internal Catch error: '" << message << '\'';
Phil Nashab036682014-06-02 07:48:03 +01008463 if( alwaysTrue() )
Phil Nash3649fdf2013-12-03 18:53:55 +00008464 throw std::logic_error( oss.str() );
8465 }
8466}
8467
8468// #included from: catch_section.hpp
8469#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
8470
8471namespace Catch {
8472
Phil Nashce562092014-07-09 07:40:37 +01008473 SectionInfo::SectionInfo
8474 ( SourceLineInfo const& _lineInfo,
8475 std::string const& _name,
8476 std::string const& _description )
8477 : name( _name ),
8478 description( _description ),
8479 lineInfo( _lineInfo )
8480 {}
8481
8482 Section::Section( SectionInfo const& info )
8483 : m_info( info ),
Phil Nash9241e432014-05-20 18:50:59 +01008484 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
Phil Nash3649fdf2013-12-03 18:53:55 +00008485 {
8486 m_timer.start();
8487 }
8488
8489 Section::~Section() {
Phil Nash0c1c9fa2015-09-27 03:28:14 -07008490 if( m_sectionIncluded ) {
8491 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
8492 if( std::uncaught_exception() )
8493 getResultCapture().sectionEndedEarly( endInfo );
8494 else
8495 getResultCapture().sectionEnded( endInfo );
8496 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008497 }
8498
8499 // This indicates whether the section should be executed or not
Phil Nashce562092014-07-09 07:40:37 +01008500 Section::operator bool() const {
Phil Nash3649fdf2013-12-03 18:53:55 +00008501 return m_sectionIncluded;
8502 }
8503
8504} // end namespace Catch
8505
8506// #included from: catch_debugger.hpp
8507#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
8508
Phil Nash3649fdf2013-12-03 18:53:55 +00008509#ifdef CATCH_PLATFORM_MAC
8510
8511 #include <assert.h>
8512 #include <stdbool.h>
8513 #include <sys/types.h>
8514 #include <unistd.h>
8515 #include <sys/sysctl.h>
8516
8517 namespace Catch{
8518
8519 // The following function is taken directly from the following technical note:
8520 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
8521
8522 // Returns true if the current process is being debugged (either
8523 // running under the debugger or has a debugger attached post facto).
8524 bool isDebuggerActive(){
8525
Phil Nash3649fdf2013-12-03 18:53:55 +00008526 int mib[4];
8527 struct kinfo_proc info;
8528 size_t size;
8529
8530 // Initialize the flags so that, if sysctl fails for some bizarre
8531 // reason, we get a predictable result.
8532
8533 info.kp_proc.p_flag = 0;
8534
8535 // Initialize mib, which tells sysctl the info we want, in this case
8536 // we're looking for information about a specific process ID.
8537
8538 mib[0] = CTL_KERN;
8539 mib[1] = KERN_PROC;
8540 mib[2] = KERN_PROC_PID;
8541 mib[3] = getpid();
8542
8543 // Call sysctl.
8544
8545 size = sizeof(info);
Phil Nashb971fe72015-07-02 08:21:38 +01008546 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) {
Phil Nash383d7c02014-10-02 19:08:19 +01008547 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
Phil Nash7eb5acc2014-01-08 17:17:31 +00008548 return false;
8549 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008550
8551 // We're being debugged if the P_TRACED flag is set.
8552
8553 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
8554 }
8555 } // namespace Catch
8556
Martin Hořeňovský9a566092017-01-20 12:49:59 +01008557#elif defined(CATCH_PLATFORM_LINUX)
8558 #include <fstream>
8559 #include <string>
8560
8561 namespace Catch{
8562 // The standard POSIX way of detecting a debugger is to attempt to
8563 // ptrace() the process, but this needs to be done from a child and not
8564 // this process itself to still allow attaching to this process later
8565 // if wanted, so is rather heavy. Under Linux we have the PID of the
8566 // "debugger" (which doesn't need to be gdb, of course, it could also
8567 // be strace, for example) in /proc/$PID/status, so just get it from
8568 // there instead.
8569 bool isDebuggerActive(){
8570 std::ifstream in("/proc/self/status");
8571 for( std::string line; std::getline(in, line); ) {
8572 static const int PREFIX_LEN = 11;
8573 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
8574 // We're traced if the PID is not 0 and no other PID starts
8575 // with 0 digit, so it's enough to check for just a single
8576 // character.
8577 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
8578 }
8579 }
8580
8581 return false;
8582 }
8583 } // namespace Catch
Phil Nash3649fdf2013-12-03 18:53:55 +00008584#elif defined(_MSC_VER)
8585 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8586 namespace Catch {
8587 bool isDebuggerActive() {
8588 return IsDebuggerPresent() != 0;
8589 }
8590 }
8591#elif defined(__MINGW32__)
8592 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8593 namespace Catch {
8594 bool isDebuggerActive() {
8595 return IsDebuggerPresent() != 0;
8596 }
8597 }
8598#else
8599 namespace Catch {
8600 inline bool isDebuggerActive() { return false; }
8601 }
8602#endif // Platform
8603
8604#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashd08cee22017-02-13 16:15:42 +00008605
Phil Nash3649fdf2013-12-03 18:53:55 +00008606 namespace Catch {
8607 void writeToDebugConsole( std::string const& text ) {
8608 ::OutputDebugStringA( text.c_str() );
8609 }
8610 }
8611#else
8612 namespace Catch {
8613 void writeToDebugConsole( std::string const& text ) {
8614 // !TBD: Need a version for Mac/ XCode and other IDEs
Phil Nash383d7c02014-10-02 19:08:19 +01008615 Catch::cout() << text;
Phil Nash3649fdf2013-12-03 18:53:55 +00008616 }
8617 }
8618#endif // Platform
8619
Phil Nashaef6cd52014-04-23 07:10:10 +01008620// #included from: catch_tostring.hpp
8621#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
8622
8623namespace Catch {
8624
Phil Nashab036682014-06-02 07:48:03 +01008625namespace Detail {
8626
Phil Nash2f6371f2015-07-23 23:06:26 +01008627 const std::string unprintableString = "{?}";
Phil Nash6a8e8ad2014-09-15 18:40:24 +01008628
Phil Nashab036682014-06-02 07:48:03 +01008629 namespace {
Phil Nash2f6371f2015-07-23 23:06:26 +01008630 const int hexThreshold = 255;
8631
Phil Nashab036682014-06-02 07:48:03 +01008632 struct Endianness {
8633 enum Arch { Big, Little };
8634
8635 static Arch which() {
8636 union _{
8637 int asInt;
8638 char asChar[sizeof (int)];
8639 } u;
8640
8641 u.asInt = 1;
8642 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
8643 }
8644 };
8645 }
8646
8647 std::string rawMemoryToString( const void *object, std::size_t size )
8648 {
8649 // Reverse order for little endian architectures
8650 int i = 0, end = static_cast<int>( size ), inc = 1;
8651 if( Endianness::which() == Endianness::Little ) {
8652 i = end-1;
8653 end = inc = -1;
8654 }
8655
8656 unsigned char const *bytes = static_cast<unsigned char const *>(object);
8657 std::ostringstream os;
8658 os << "0x" << std::setfill('0') << std::hex;
8659 for( ; i != end; i += inc )
8660 os << std::setw(2) << static_cast<unsigned>(bytes[i]);
8661 return os.str();
8662 }
8663}
8664
Phil Nashaef6cd52014-04-23 07:10:10 +01008665std::string toString( std::string const& value ) {
8666 std::string s = value;
8667 if( getCurrentContext().getConfig()->showInvisibles() ) {
8668 for(size_t i = 0; i < s.size(); ++i ) {
8669 std::string subs;
8670 switch( s[i] ) {
8671 case '\n': subs = "\\n"; break;
8672 case '\t': subs = "\\t"; break;
8673 default: break;
8674 }
8675 if( !subs.empty() ) {
8676 s = s.substr( 0, i ) + subs + s.substr( i+1 );
8677 ++i;
8678 }
8679 }
8680 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008681 return '"' + s + '"';
Phil Nashaef6cd52014-04-23 07:10:10 +01008682}
8683std::string toString( std::wstring const& value ) {
8684
8685 std::string s;
8686 s.reserve( value.size() );
8687 for(size_t i = 0; i < value.size(); ++i )
8688 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
Phil Nash13f98432014-12-12 08:11:18 +00008689 return Catch::toString( s );
Phil Nashaef6cd52014-04-23 07:10:10 +01008690}
8691
8692std::string toString( const char* const value ) {
8693 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
8694}
8695
8696std::string toString( char* const value ) {
8697 return Catch::toString( static_cast<const char*>( value ) );
8698}
8699
Phil Nash544bf332014-08-20 08:09:32 +01008700std::string toString( const wchar_t* const value )
8701{
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008702 return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
Phil Nash544bf332014-08-20 08:09:32 +01008703}
8704
8705std::string toString( wchar_t* const value )
8706{
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008707 return Catch::toString( static_cast<const wchar_t*>( value ) );
Phil Nash544bf332014-08-20 08:09:32 +01008708}
8709
Phil Nashaef6cd52014-04-23 07:10:10 +01008710std::string toString( int value ) {
8711 std::ostringstream oss;
Phil Nashc51e8682015-05-21 06:16:15 +01008712 oss << value;
Phil Nash2f6371f2015-07-23 23:06:26 +01008713 if( value > Detail::hexThreshold )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008714 oss << " (0x" << std::hex << value << ')';
Phil Nashaef6cd52014-04-23 07:10:10 +01008715 return oss.str();
8716}
8717
8718std::string toString( unsigned long value ) {
8719 std::ostringstream oss;
Phil Nashc51e8682015-05-21 06:16:15 +01008720 oss << value;
Phil Nash2f6371f2015-07-23 23:06:26 +01008721 if( value > Detail::hexThreshold )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008722 oss << " (0x" << std::hex << value << ')';
Phil Nashaef6cd52014-04-23 07:10:10 +01008723 return oss.str();
8724}
8725
8726std::string toString( unsigned int value ) {
Phil Nash13f98432014-12-12 08:11:18 +00008727 return Catch::toString( static_cast<unsigned long>( value ) );
Phil Nashaef6cd52014-04-23 07:10:10 +01008728}
8729
Phil Nash28c2e072014-07-09 19:22:49 +01008730template<typename T>
8731std::string fpToString( T value, int precision ) {
Phil Nashaef6cd52014-04-23 07:10:10 +01008732 std::ostringstream oss;
Phil Nash28c2e072014-07-09 19:22:49 +01008733 oss << std::setprecision( precision )
Phil Nashaef6cd52014-04-23 07:10:10 +01008734 << std::fixed
8735 << value;
8736 std::string d = oss.str();
8737 std::size_t i = d.find_last_not_of( '0' );
8738 if( i != std::string::npos && i != d.size()-1 ) {
8739 if( d[i] == '.' )
8740 i++;
8741 d = d.substr( 0, i+1 );
8742 }
8743 return d;
8744}
8745
Phil Nash28c2e072014-07-09 19:22:49 +01008746std::string toString( const double value ) {
8747 return fpToString( value, 10 );
8748}
8749std::string toString( const float value ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008750 return fpToString( value, 5 ) + 'f';
Phil Nash28c2e072014-07-09 19:22:49 +01008751}
8752
Phil Nashaef6cd52014-04-23 07:10:10 +01008753std::string toString( bool value ) {
8754 return value ? "true" : "false";
8755}
8756
8757std::string toString( char value ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008758 if ( value == '\r' )
8759 return "'\\r'";
8760 if ( value == '\f' )
8761 return "'\\f'";
8762 if ( value == '\n' )
8763 return "'\\n'";
8764 if ( value == '\t' )
8765 return "'\\t'";
8766 if ( '\0' <= value && value < ' ' )
8767 return toString( static_cast<unsigned int>( value ) );
8768 char chstr[] = "' '";
8769 chstr[1] = value;
8770 return chstr;
Phil Nashaef6cd52014-04-23 07:10:10 +01008771}
8772
8773std::string toString( signed char value ) {
8774 return toString( static_cast<char>( value ) );
8775}
8776
8777std::string toString( unsigned char value ) {
8778 return toString( static_cast<char>( value ) );
8779}
8780
Phil Nash2f6371f2015-07-23 23:06:26 +01008781#ifdef CATCH_CONFIG_CPP11_LONG_LONG
8782std::string toString( long long value ) {
8783 std::ostringstream oss;
8784 oss << value;
8785 if( value > Detail::hexThreshold )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008786 oss << " (0x" << std::hex << value << ')';
Phil Nash2f6371f2015-07-23 23:06:26 +01008787 return oss.str();
8788}
8789std::string toString( unsigned long long value ) {
8790 std::ostringstream oss;
8791 oss << value;
8792 if( value > Detail::hexThreshold )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008793 oss << " (0x" << std::hex << value << ')';
Phil Nash2f6371f2015-07-23 23:06:26 +01008794 return oss.str();
8795}
8796#endif
8797
Phil Nashaef6cd52014-04-23 07:10:10 +01008798#ifdef CATCH_CONFIG_CPP11_NULLPTR
8799std::string toString( std::nullptr_t ) {
8800 return "nullptr";
8801}
8802#endif
8803
8804#ifdef __OBJC__
8805 std::string toString( NSString const * const& nsstring ) {
8806 if( !nsstring )
8807 return "nil";
Phil Nashacdd3b52014-06-30 07:35:36 +01008808 return "@" + toString([nsstring UTF8String]);
Phil Nashaef6cd52014-04-23 07:10:10 +01008809 }
8810 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
8811 if( !nsstring )
8812 return "nil";
Phil Nashacdd3b52014-06-30 07:35:36 +01008813 return "@" + toString([nsstring UTF8String]);
Phil Nashaef6cd52014-04-23 07:10:10 +01008814 }
8815 std::string toString( NSObject* const& nsObject ) {
8816 return toString( [nsObject description] );
8817 }
8818#endif
8819
8820} // end namespace Catch
8821
Phil Nashab036682014-06-02 07:48:03 +01008822// #included from: catch_result_builder.hpp
8823#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
8824
8825namespace Catch {
8826
Phil Nash93a842e2015-07-13 06:36:07 +01008827 std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008828 return secondArg.empty() || secondArg == "\"\""
Phil Nash93a842e2015-07-13 06:36:07 +01008829 ? capturedExpression
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008830 : capturedExpression + ", " + secondArg;
Phil Nash93a842e2015-07-13 06:36:07 +01008831 }
Phil Nashab036682014-06-02 07:48:03 +01008832 ResultBuilder::ResultBuilder( char const* macroName,
8833 SourceLineInfo const& lineInfo,
8834 char const* capturedExpression,
Phil Nash93a842e2015-07-13 06:36:07 +01008835 ResultDisposition::Flags resultDisposition,
8836 char const* secondArg )
8837 : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
Phil Nashab036682014-06-02 07:48:03 +01008838 m_shouldDebugBreak( false ),
8839 m_shouldThrow( false )
8840 {}
8841
8842 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
8843 m_data.resultType = result;
8844 return *this;
8845 }
8846 ResultBuilder& ResultBuilder::setResultType( bool result ) {
8847 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
8848 return *this;
8849 }
Phil Nashab036682014-06-02 07:48:03 +01008850
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008851 void ResultBuilder::endExpression( DecomposedExpression const& expr ) {
8852 AssertionResult result = build( expr );
8853 handleResult( result );
Phil Nashab036682014-06-02 07:48:03 +01008854 }
8855
8856 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
8857 m_assertionInfo.resultDisposition = resultDisposition;
8858 m_stream.oss << Catch::translateActiveException();
8859 captureResult( ResultWas::ThrewException );
8860 }
8861
8862 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
8863 setResultType( resultType );
8864 captureExpression();
8865 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008866
Phil Nash93a842e2015-07-13 06:36:07 +01008867 void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008868 if( expectedMessage.empty() )
Phil Nash0952b762017-02-28 14:19:09 +00008869 captureExpectedException( Matchers::Impl::MatchAllOf<std::string>() );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008870 else
8871 captureExpectedException( Matchers::Equals( expectedMessage ) );
8872 }
8873
Phil Nash0952b762017-02-28 14:19:09 +00008874 void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher ) {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008875
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008876 assert( !isFalseTest( m_assertionInfo.resultDisposition ) );
Phil Nash93a842e2015-07-13 06:36:07 +01008877 AssertionResultData data = m_data;
8878 data.resultType = ResultWas::Ok;
8879 data.reconstructedExpression = m_assertionInfo.capturedExpression;
Phil Nash93a842e2015-07-13 06:36:07 +01008880
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008881 std::string actualMessage = Catch::translateActiveException();
8882 if( !matcher.match( actualMessage ) ) {
8883 data.resultType = ResultWas::ExpressionFailed;
8884 data.reconstructedExpression = actualMessage;
Phil Nash93a842e2015-07-13 06:36:07 +01008885 }
8886 AssertionResult result( m_assertionInfo, data );
8887 handleResult( result );
8888 }
Phil Nashab036682014-06-02 07:48:03 +01008889
8890 void ResultBuilder::captureExpression() {
8891 AssertionResult result = build();
Phil Nash93a842e2015-07-13 06:36:07 +01008892 handleResult( result );
8893 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008894
Phil Nash93a842e2015-07-13 06:36:07 +01008895 void ResultBuilder::handleResult( AssertionResult const& result )
8896 {
Phil Nashab036682014-06-02 07:48:03 +01008897 getResultCapture().assertionEnded( result );
8898
8899 if( !result.isOk() ) {
8900 if( getCurrentContext().getConfig()->shouldDebugBreak() )
8901 m_shouldDebugBreak = true;
Phil Nash318c9362015-05-19 18:40:00 +01008902 if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
Phil Nashab036682014-06-02 07:48:03 +01008903 m_shouldThrow = true;
8904 }
8905 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008906
Phil Nashab036682014-06-02 07:48:03 +01008907 void ResultBuilder::react() {
Phil Nash0952b762017-02-28 14:19:09 +00008908#if defined(CATCH_CONFIG_FAST_COMPILE)
8909 if (m_shouldDebugBreak) {
8910 ///////////////////////////////////////////////////////////////////
8911 // To inspect the state during test, you need to go one level up the callstack
8912 // To go back to the test and change execution, jump over the throw statement
8913 ///////////////////////////////////////////////////////////////////
8914 CATCH_BREAK_INTO_DEBUGGER();
8915 }
8916#endif
Phil Nashab036682014-06-02 07:48:03 +01008917 if( m_shouldThrow )
8918 throw Catch::TestFailureException();
8919 }
8920
8921 bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
8922 bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
8923
8924 AssertionResult ResultBuilder::build() const
8925 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008926 return build( *this );
8927 }
Phil Nashab036682014-06-02 07:48:03 +01008928
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008929 // CAVEAT: The returned AssertionResult stores a pointer to the argument expr,
8930 // a temporary DecomposedExpression, which in turn holds references to
8931 // operands, possibly temporary as well.
8932 // It should immediately be passed to handleResult; if the expression
8933 // needs to be reported, its string expansion must be composed before
8934 // the temporaries are destroyed.
8935 AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const
8936 {
8937 assert( m_data.resultType != ResultWas::Unknown );
Phil Nashab036682014-06-02 07:48:03 +01008938 AssertionResultData data = m_data;
8939
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008940 // Flip bool results if FalseTest flag is set
8941 if( isFalseTest( m_assertionInfo.resultDisposition ) ) {
8942 data.negate( expr.isBinaryExpression() );
Phil Nashab036682014-06-02 07:48:03 +01008943 }
8944
8945 data.message = m_stream.oss.str();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008946 data.decomposedExpression = &expr; // for lazy reconstruction
Phil Nashab036682014-06-02 07:48:03 +01008947 return AssertionResult( m_assertionInfo, data );
8948 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008949
8950 void ResultBuilder::reconstructExpression( std::string& dest ) const {
8951 dest = m_assertionInfo.capturedExpression;
Phil Nashab036682014-06-02 07:48:03 +01008952 }
8953
8954} // end namespace Catch
8955
Phil Nashacdd3b52014-06-30 07:35:36 +01008956// #included from: catch_tag_alias_registry.hpp
8957#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
8958
8959// #included from: catch_tag_alias_registry.h
8960#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
8961
8962#include <map>
8963
8964namespace Catch {
8965
8966 class TagAliasRegistry : public ITagAliasRegistry {
8967 public:
8968 virtual ~TagAliasRegistry();
8969 virtual Option<TagAlias> find( std::string const& alias ) const;
8970 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
8971 void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
8972 static TagAliasRegistry& get();
8973
8974 private:
8975 std::map<std::string, TagAlias> m_registry;
8976 };
8977
8978} // end namespace Catch
8979
Phil Nashacdd3b52014-06-30 07:35:36 +01008980namespace Catch {
8981
8982 TagAliasRegistry::~TagAliasRegistry() {}
8983
8984 Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
8985 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
8986 if( it != m_registry.end() )
8987 return it->second;
8988 else
8989 return Option<TagAlias>();
8990 }
8991
8992 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
8993 std::string expandedTestSpec = unexpandedTestSpec;
8994 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
8995 it != itEnd;
8996 ++it ) {
8997 std::size_t pos = expandedTestSpec.find( it->first );
8998 if( pos != std::string::npos ) {
8999 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
9000 it->second.tag +
9001 expandedTestSpec.substr( pos + it->first.size() );
9002 }
9003 }
9004 return expandedTestSpec;
9005 }
9006
9007 void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
9008
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009009 if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) {
Phil Nashacdd3b52014-06-30 07:35:36 +01009010 std::ostringstream oss;
9011 oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo;
9012 throw std::domain_error( oss.str().c_str() );
9013 }
9014 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
9015 std::ostringstream oss;
9016 oss << "error: tag alias, \"" << alias << "\" already registered.\n"
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009017 << "\tFirst seen at " << find(alias)->lineInfo << '\n'
Phil Nashacdd3b52014-06-30 07:35:36 +01009018 << "\tRedefined at " << lineInfo;
9019 throw std::domain_error( oss.str().c_str() );
9020 }
9021 }
9022
9023 TagAliasRegistry& TagAliasRegistry::get() {
9024 static TagAliasRegistry instance;
9025 return instance;
9026
9027 }
9028
9029 ITagAliasRegistry::~ITagAliasRegistry() {}
9030 ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); }
9031
9032 RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
9033 try {
9034 TagAliasRegistry::get().add( alias, tag, lineInfo );
9035 }
9036 catch( std::exception& ex ) {
9037 Colour colourGuard( Colour::Red );
Phil Nash383d7c02014-10-02 19:08:19 +01009038 Catch::cerr() << ex.what() << std::endl;
Phil Nashacdd3b52014-06-30 07:35:36 +01009039 exit(1);
9040 }
9041 }
9042
9043} // end namespace Catch
9044
Phil Nash0952b762017-02-28 14:19:09 +00009045// #included from: catch_matchers_string.hpp
9046
9047namespace Catch {
9048namespace Matchers {
9049
9050 namespace StdString {
9051
9052 CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
9053 : m_caseSensitivity( caseSensitivity ),
9054 m_str( adjustString( str ) )
9055 {}
9056 std::string CasedString::adjustString( std::string const& str ) const {
9057 return m_caseSensitivity == CaseSensitive::No
9058 ? toLower( str )
9059 : str;
9060 }
9061 std::string CasedString::caseSensitivitySuffix() const {
9062 return m_caseSensitivity == CaseSensitive::No
9063 ? " (case insensitive)"
9064 : std::string();
9065 }
9066
9067 StringMatcherBase::StringMatcherBase( std::string operation, CasedString const& comparator )
9068 : m_comparator( comparator ),
9069 m_operation( operation ) {
9070 }
9071
9072 std::string StringMatcherBase::describe() const {
9073 std::string description;
9074 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
9075 m_comparator.caseSensitivitySuffix().size());
9076 description += m_operation;
9077 description += ": \"";
9078 description += m_comparator.m_str;
9079 description += "\"";
9080 description += m_comparator.caseSensitivitySuffix();
9081 return description;
9082 }
9083
9084 EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}
9085
9086 bool EqualsMatcher::match( std::string const& source ) const {
9087 return m_comparator.adjustString( source ) == m_comparator.m_str;
9088 }
9089
9090 ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}
9091
9092 bool ContainsMatcher::match( std::string const& source ) const {
9093 return contains( m_comparator.adjustString( source ), m_comparator.m_str );
9094 }
9095
9096 StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}
9097
9098 bool StartsWithMatcher::match( std::string const& source ) const {
9099 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9100 }
9101
9102 EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}
9103
9104 bool EndsWithMatcher::match( std::string const& source ) const {
9105 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9106 }
9107
9108 } // namespace StdString
9109
9110 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9111 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
9112 }
9113 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9114 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
9115 }
9116 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9117 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9118 }
9119 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9120 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9121 }
9122
9123} // namespace Matchers
9124} // namespace Catch
Phil Nashe73583d2015-08-07 17:30:34 +01009125// #included from: ../reporters/catch_reporter_multi.hpp
9126#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
9127
9128namespace Catch {
9129
9130class MultipleReporters : public SharedImpl<IStreamingReporter> {
9131 typedef std::vector<Ptr<IStreamingReporter> > Reporters;
9132 Reporters m_reporters;
9133
9134public:
9135 void add( Ptr<IStreamingReporter> const& reporter ) {
9136 m_reporters.push_back( reporter );
9137 }
9138
9139public: // IStreamingReporter
9140
9141 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9142 return m_reporters[0]->getPreferences();
9143 }
9144
9145 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
9146 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9147 it != itEnd;
9148 ++it )
9149 (*it)->noMatchingTestCases( spec );
9150 }
9151
9152 virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
9153 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9154 it != itEnd;
9155 ++it )
9156 (*it)->testRunStarting( testRunInfo );
9157 }
9158
9159 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
9160 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9161 it != itEnd;
9162 ++it )
9163 (*it)->testGroupStarting( groupInfo );
9164 }
9165
9166 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
9167 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9168 it != itEnd;
9169 ++it )
9170 (*it)->testCaseStarting( testInfo );
9171 }
9172
9173 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
9174 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9175 it != itEnd;
9176 ++it )
9177 (*it)->sectionStarting( sectionInfo );
9178 }
9179
9180 virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
9181 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9182 it != itEnd;
9183 ++it )
9184 (*it)->assertionStarting( assertionInfo );
9185 }
9186
9187 // The return value indicates if the messages buffer should be cleared:
9188 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
9189 bool clearBuffer = false;
9190 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9191 it != itEnd;
9192 ++it )
9193 clearBuffer |= (*it)->assertionEnded( assertionStats );
9194 return clearBuffer;
9195 }
9196
9197 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
9198 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9199 it != itEnd;
9200 ++it )
9201 (*it)->sectionEnded( sectionStats );
9202 }
9203
9204 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
9205 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9206 it != itEnd;
9207 ++it )
9208 (*it)->testCaseEnded( testCaseStats );
9209 }
9210
9211 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
9212 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9213 it != itEnd;
9214 ++it )
9215 (*it)->testGroupEnded( testGroupStats );
9216 }
9217
9218 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
9219 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9220 it != itEnd;
9221 ++it )
9222 (*it)->testRunEnded( testRunStats );
9223 }
9224
9225 virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
9226 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9227 it != itEnd;
9228 ++it )
9229 (*it)->skipTest( testInfo );
9230 }
Phil Nash92b141e2016-04-28 08:13:00 +01009231
9232 virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
9233 return this;
9234 }
9235
Phil Nashe73583d2015-08-07 17:30:34 +01009236};
9237
9238Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
9239 Ptr<IStreamingReporter> resultingReporter;
9240
9241 if( existingReporter ) {
Phil Nash92b141e2016-04-28 08:13:00 +01009242 MultipleReporters* multi = existingReporter->tryAsMulti();
Phil Nashe73583d2015-08-07 17:30:34 +01009243 if( !multi ) {
9244 multi = new MultipleReporters;
9245 resultingReporter = Ptr<IStreamingReporter>( multi );
9246 if( existingReporter )
9247 multi->add( existingReporter );
9248 }
9249 else
9250 resultingReporter = existingReporter;
9251 multi->add( additionalReporter );
9252 }
9253 else
9254 resultingReporter = additionalReporter;
9255
9256 return resultingReporter;
9257}
9258
9259} // end namespace Catch
9260
Phil Nash3faa4122013-08-15 19:09:07 +01009261// #included from: ../reporters/catch_reporter_xml.hpp
9262#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
Phil Nash56d5c422012-08-23 20:08:50 +01009263
Phil Nash3649fdf2013-12-03 18:53:55 +00009264// #included from: catch_reporter_bases.hpp
9265#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
9266
Phil Nashb7713942014-12-22 07:42:57 +00009267#include <cstring>
Phil Nash0952b762017-02-28 14:19:09 +00009268#include <assert.h>
Phil Nashb7713942014-12-22 07:42:57 +00009269
Phil Nash3649fdf2013-12-03 18:53:55 +00009270namespace Catch {
9271
9272 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
9273
9274 StreamingReporterBase( ReporterConfig const& _config )
9275 : m_config( _config.fullConfig() ),
9276 stream( _config.stream() )
Phil Nashe73583d2015-08-07 17:30:34 +01009277 {
9278 m_reporterPrefs.shouldRedirectStdOut = false;
9279 }
Phil Nash3649fdf2013-12-03 18:53:55 +00009280
Phil Nashe73583d2015-08-07 17:30:34 +01009281 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9282 return m_reporterPrefs;
9283 }
Phil Nash3649fdf2013-12-03 18:53:55 +00009284
Phil Nashe73583d2015-08-07 17:30:34 +01009285 virtual ~StreamingReporterBase() CATCH_OVERRIDE;
Phil Nash3649fdf2013-12-03 18:53:55 +00009286
Phil Nashe73583d2015-08-07 17:30:34 +01009287 virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {}
9288
9289 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009290 currentTestRunInfo = _testRunInfo;
9291 }
Phil Nashe73583d2015-08-07 17:30:34 +01009292 virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009293 currentGroupInfo = _groupInfo;
9294 }
9295
Phil Nashe73583d2015-08-07 17:30:34 +01009296 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009297 currentTestCaseInfo = _testInfo;
9298 }
Phil Nashe73583d2015-08-07 17:30:34 +01009299 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009300 m_sectionStack.push_back( _sectionInfo );
9301 }
9302
Phil Nashe73583d2015-08-07 17:30:34 +01009303 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009304 m_sectionStack.pop_back();
9305 }
Phil Nashe73583d2015-08-07 17:30:34 +01009306 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009307 currentTestCaseInfo.reset();
Phil Nash3649fdf2013-12-03 18:53:55 +00009308 }
Phil Nashe73583d2015-08-07 17:30:34 +01009309 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009310 currentGroupInfo.reset();
9311 }
Phil Nashe73583d2015-08-07 17:30:34 +01009312 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009313 currentTestCaseInfo.reset();
9314 currentGroupInfo.reset();
9315 currentTestRunInfo.reset();
9316 }
9317
Phil Nashe73583d2015-08-07 17:30:34 +01009318 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {
Phil Nash92f08362014-12-22 20:18:05 +00009319 // Don't do anything with this by default.
9320 // It can optionally be overridden in the derived class.
9321 }
9322
Phil Nash7e346192015-11-03 08:00:43 +00009323 Ptr<IConfig const> m_config;
Phil Nash3649fdf2013-12-03 18:53:55 +00009324 std::ostream& stream;
9325
9326 LazyStat<TestRunInfo> currentTestRunInfo;
9327 LazyStat<GroupInfo> currentGroupInfo;
9328 LazyStat<TestCaseInfo> currentTestCaseInfo;
9329
9330 std::vector<SectionInfo> m_sectionStack;
Phil Nashe73583d2015-08-07 17:30:34 +01009331 ReporterPreferences m_reporterPrefs;
Phil Nash3649fdf2013-12-03 18:53:55 +00009332 };
9333
9334 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
9335 template<typename T, typename ChildNodeT>
9336 struct Node : SharedImpl<> {
9337 explicit Node( T const& _value ) : value( _value ) {}
9338 virtual ~Node() {}
9339
9340 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
9341 T value;
9342 ChildNodes children;
9343 };
9344 struct SectionNode : SharedImpl<> {
9345 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
9346 virtual ~SectionNode();
9347
9348 bool operator == ( SectionNode const& other ) const {
9349 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
9350 }
9351 bool operator == ( Ptr<SectionNode> const& other ) const {
9352 return operator==( *other );
9353 }
9354
9355 SectionStats stats;
9356 typedef std::vector<Ptr<SectionNode> > ChildSections;
9357 typedef std::vector<AssertionStats> Assertions;
9358 ChildSections childSections;
9359 Assertions assertions;
9360 std::string stdOut;
9361 std::string stdErr;
9362 };
Phil Nasheb760f62013-12-18 08:38:33 +00009363
9364 struct BySectionInfo {
9365 BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009366 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
Phil Nasheb760f62013-12-18 08:38:33 +00009367 bool operator() ( Ptr<SectionNode> const& node ) const {
9368 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
9369 }
9370 private:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009371 void operator=( BySectionInfo const& );
Phil Nasheb760f62013-12-18 08:38:33 +00009372 SectionInfo const& m_other;
9373 };
Phil Nash3649fdf2013-12-03 18:53:55 +00009374
9375 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
9376 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
9377 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
9378
9379 CumulativeReporterBase( ReporterConfig const& _config )
9380 : m_config( _config.fullConfig() ),
9381 stream( _config.stream() )
Phil Nashe73583d2015-08-07 17:30:34 +01009382 {
9383 m_reporterPrefs.shouldRedirectStdOut = false;
9384 }
Phil Nash3649fdf2013-12-03 18:53:55 +00009385 ~CumulativeReporterBase();
9386
Phil Nashe73583d2015-08-07 17:30:34 +01009387 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9388 return m_reporterPrefs;
9389 }
Phil Nash3649fdf2013-12-03 18:53:55 +00009390
Phil Nashe73583d2015-08-07 17:30:34 +01009391 virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {}
9392 virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {}
Phil Nash3649fdf2013-12-03 18:53:55 +00009393
Phil Nashe73583d2015-08-07 17:30:34 +01009394 virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {}
9395
9396 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009397 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
9398 Ptr<SectionNode> node;
9399 if( m_sectionStack.empty() ) {
9400 if( !m_rootSection )
9401 m_rootSection = new SectionNode( incompleteStats );
9402 node = m_rootSection;
9403 }
9404 else {
9405 SectionNode& parentNode = *m_sectionStack.back();
9406 SectionNode::ChildSections::const_iterator it =
Phil Nasheb760f62013-12-18 08:38:33 +00009407 std::find_if( parentNode.childSections.begin(),
9408 parentNode.childSections.end(),
9409 BySectionInfo( sectionInfo ) );
Phil Nash3649fdf2013-12-03 18:53:55 +00009410 if( it == parentNode.childSections.end() ) {
9411 node = new SectionNode( incompleteStats );
9412 parentNode.childSections.push_back( node );
9413 }
9414 else
9415 node = *it;
9416 }
9417 m_sectionStack.push_back( node );
9418 m_deepestSection = node;
9419 }
9420
Phil Nashe73583d2015-08-07 17:30:34 +01009421 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
Phil Nash3649fdf2013-12-03 18:53:55 +00009422
Phil Nashe5537842016-04-25 18:56:50 +01009423 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009424 assert( !m_sectionStack.empty() );
9425 SectionNode& sectionNode = *m_sectionStack.back();
9426 sectionNode.assertions.push_back( assertionStats );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009427 // AssertionResult holds a pointer to a temporary DecomposedExpression,
9428 // which getExpandedExpression() calls to build the expression string.
9429 // Our section stack copy of the assertionResult will likely outlive the
9430 // temporary, so it must be expanded or discarded now to avoid calling
9431 // a destroyed object later.
9432 prepareExpandedExpression( sectionNode.assertions.back().assertionResult );
Phil Nash3649fdf2013-12-03 18:53:55 +00009433 return true;
9434 }
Phil Nashe73583d2015-08-07 17:30:34 +01009435 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009436 assert( !m_sectionStack.empty() );
9437 SectionNode& node = *m_sectionStack.back();
9438 node.stats = sectionStats;
9439 m_sectionStack.pop_back();
9440 }
Phil Nashe73583d2015-08-07 17:30:34 +01009441 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009442 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
9443 assert( m_sectionStack.size() == 0 );
9444 node->children.push_back( m_rootSection );
9445 m_testCases.push_back( node );
9446 m_rootSection.reset();
9447
9448 assert( m_deepestSection );
9449 m_deepestSection->stdOut = testCaseStats.stdOut;
9450 m_deepestSection->stdErr = testCaseStats.stdErr;
9451 }
Phil Nashe73583d2015-08-07 17:30:34 +01009452 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009453 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
9454 node->children.swap( m_testCases );
9455 m_testGroups.push_back( node );
9456 }
Phil Nashe73583d2015-08-07 17:30:34 +01009457 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009458 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
9459 node->children.swap( m_testGroups );
9460 m_testRuns.push_back( node );
Phil Nasha6d74bd2013-12-11 08:28:15 +00009461 testRunEndedCumulative();
Phil Nash3649fdf2013-12-03 18:53:55 +00009462 }
Phil Nasha6d74bd2013-12-11 08:28:15 +00009463 virtual void testRunEndedCumulative() = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00009464
Phil Nashe73583d2015-08-07 17:30:34 +01009465 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
Phil Nash92f08362014-12-22 20:18:05 +00009466
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009467 virtual void prepareExpandedExpression( AssertionResult& result ) const {
9468 if( result.isOk() )
9469 result.discardDecomposedExpression();
9470 else
9471 result.expandDecomposedExpression();
9472 }
9473
Phil Nash7e346192015-11-03 08:00:43 +00009474 Ptr<IConfig const> m_config;
Phil Nash3649fdf2013-12-03 18:53:55 +00009475 std::ostream& stream;
9476 std::vector<AssertionStats> m_assertions;
9477 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
9478 std::vector<Ptr<TestCaseNode> > m_testCases;
9479 std::vector<Ptr<TestGroupNode> > m_testGroups;
9480
9481 std::vector<Ptr<TestRunNode> > m_testRuns;
9482
9483 Ptr<SectionNode> m_rootSection;
9484 Ptr<SectionNode> m_deepestSection;
9485 std::vector<Ptr<SectionNode> > m_sectionStack;
Phil Nashe73583d2015-08-07 17:30:34 +01009486 ReporterPreferences m_reporterPrefs;
Phil Nash3649fdf2013-12-03 18:53:55 +00009487
9488 };
9489
Phil Nash576aff62014-12-21 00:21:23 +00009490 template<char C>
9491 char const* getLineOfChars() {
9492 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
9493 if( !*line ) {
Phil Nashd08cee22017-02-13 16:15:42 +00009494 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
Phil Nash576aff62014-12-21 00:21:23 +00009495 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
9496 }
9497 return line;
9498 }
9499
Phil Nashe73583d2015-08-07 17:30:34 +01009500 struct TestEventListenerBase : StreamingReporterBase {
9501 TestEventListenerBase( ReporterConfig const& _config )
9502 : StreamingReporterBase( _config )
9503 {}
9504
9505 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
Phil Nash08844e72015-11-05 18:52:18 +00009506 virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
Phil Nashe73583d2015-08-07 17:30:34 +01009507 return false;
9508 }
9509 };
9510
Phil Nash3649fdf2013-12-03 18:53:55 +00009511} // end namespace Catch
9512
Phil Nash56d5c422012-08-23 20:08:50 +01009513// #included from: ../internal/catch_reporter_registrars.hpp
9514#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
9515
9516namespace Catch {
9517
9518 template<typename T>
Phil Nasha1fbfea2012-12-01 23:57:18 +00009519 class LegacyReporterRegistrar {
9520
9521 class ReporterFactory : public IReporterFactory {
Phil Nash8defc712013-04-24 19:10:02 +01009522 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
Phil Nash786959d2013-06-07 19:07:50 +01009523 return new LegacyReporterAdapter( new T( config ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00009524 }
9525
9526 virtual std::string getDescription() const {
9527 return T::getDescription();
9528 }
9529 };
9530
9531 public:
9532
Phil Nash8defc712013-04-24 19:10:02 +01009533 LegacyReporterRegistrar( std::string const& name ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00009534 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
9535 }
9536 };
9537
9538 template<typename T>
Phil Nash56d5c422012-08-23 20:08:50 +01009539 class ReporterRegistrar {
9540
Phil Nashe73583d2015-08-07 17:30:34 +01009541 class ReporterFactory : public SharedImpl<IReporterFactory> {
Phil Nash56d5c422012-08-23 20:08:50 +01009542
Phil Nasha1fbfea2012-12-01 23:57:18 +00009543 // *** Please Note ***:
9544 // - If you end up here looking at a compiler error because it's trying to register
9545 // your custom reporter class be aware that the native reporter interface has changed
9546 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
9547 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
9548 // However please consider updating to the new interface as the old one is now
9549 // deprecated and will probably be removed quite soon!
9550 // Please contact me via github if you have any questions at all about this.
9551 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
9552 // no idea who is actually using custom reporters at all (possibly no-one!).
9553 // The new interface is designed to minimise exposure to interface changes in the future.
Phil Nash8defc712013-04-24 19:10:02 +01009554 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01009555 return new T( config );
9556 }
9557
9558 virtual std::string getDescription() const {
9559 return T::getDescription();
9560 }
9561 };
9562
9563 public:
9564
Phil Nash8defc712013-04-24 19:10:02 +01009565 ReporterRegistrar( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009566 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
9567 }
9568 };
Phil Nashe73583d2015-08-07 17:30:34 +01009569
9570 template<typename T>
9571 class ListenerRegistrar {
9572
9573 class ListenerFactory : public SharedImpl<IReporterFactory> {
9574
9575 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
9576 return new T( config );
9577 }
9578 virtual std::string getDescription() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009579 return std::string();
Phil Nashe73583d2015-08-07 17:30:34 +01009580 }
9581 };
9582
9583 public:
9584
9585 ListenerRegistrar() {
9586 getMutableRegistryHub().registerListener( new ListenerFactory() );
9587 }
9588 };
Phil Nash56d5c422012-08-23 20:08:50 +01009589}
9590
Phil Nasha1fbfea2012-12-01 23:57:18 +00009591#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
Phil Nash380f98e2013-10-17 22:45:21 +01009592 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
Phil Nashe73583d2015-08-07 17:30:34 +01009593
Phil Nash56d5c422012-08-23 20:08:50 +01009594#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
Phil Nash380f98e2013-10-17 22:45:21 +01009595 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
Phil Nash56d5c422012-08-23 20:08:50 +01009596
Phil Nashe73583d2015-08-07 17:30:34 +01009597#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
9598 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
9599
Phil Nash56d5c422012-08-23 20:08:50 +01009600// #included from: ../internal/catch_xmlwriter.hpp
9601#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
9602
9603#include <sstream>
9604#include <string>
9605#include <vector>
Phil Nash2f6371f2015-07-23 23:06:26 +01009606#include <iomanip>
Phil Nash56d5c422012-08-23 20:08:50 +01009607
9608namespace Catch {
9609
Phil Nash2f6371f2015-07-23 23:06:26 +01009610 class XmlEncode {
9611 public:
9612 enum ForWhat { ForTextNodes, ForAttributes };
9613
9614 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
9615 : m_str( str ),
9616 m_forWhat( forWhat )
9617 {}
9618
9619 void encodeTo( std::ostream& os ) const {
9620
9621 // Apostrophe escaping not necessary if we always use " to write attributes
9622 // (see: http://www.w3.org/TR/xml/#syntax)
9623
9624 for( std::size_t i = 0; i < m_str.size(); ++ i ) {
9625 char c = m_str[i];
9626 switch( c ) {
9627 case '<': os << "&lt;"; break;
9628 case '&': os << "&amp;"; break;
9629
9630 case '>':
9631 // See: http://www.w3.org/TR/xml/#syntax
9632 if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
9633 os << "&gt;";
9634 else
9635 os << c;
9636 break;
9637
9638 case '\"':
9639 if( m_forWhat == ForAttributes )
9640 os << "&quot;";
9641 else
9642 os << c;
9643 break;
9644
9645 default:
Phil Nash40f60682016-09-27 10:46:22 +01009646 // Escape control chars - based on contribution by @espenalb in PR #465 and
9647 // by @mrpi PR #588
Phil Nashd08cee22017-02-13 16:15:42 +00009648 if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) {
9649 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
9650 os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
9651 << static_cast<int>( c );
9652 }
Phil Nash2f6371f2015-07-23 23:06:26 +01009653 else
9654 os << c;
9655 }
9656 }
9657 }
9658
9659 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
9660 xmlEncode.encodeTo( os );
9661 return os;
9662 }
9663
9664 private:
9665 std::string m_str;
9666 ForWhat m_forWhat;
9667 };
9668
Phil Nash56d5c422012-08-23 20:08:50 +01009669 class XmlWriter {
9670 public:
9671
9672 class ScopedElement {
9673 public:
9674 ScopedElement( XmlWriter* writer )
9675 : m_writer( writer )
9676 {}
9677
Phil Nash8defc712013-04-24 19:10:02 +01009678 ScopedElement( ScopedElement const& other )
Phil Nash56d5c422012-08-23 20:08:50 +01009679 : m_writer( other.m_writer ){
Phil Nashb971fe72015-07-02 08:21:38 +01009680 other.m_writer = CATCH_NULL;
Phil Nash56d5c422012-08-23 20:08:50 +01009681 }
9682
9683 ~ScopedElement() {
9684 if( m_writer )
9685 m_writer->endElement();
9686 }
9687
Phil Nash8defc712013-04-24 19:10:02 +01009688 ScopedElement& writeText( std::string const& text, bool indent = true ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00009689 m_writer->writeText( text, indent );
Phil Nash56d5c422012-08-23 20:08:50 +01009690 return *this;
9691 }
9692
9693 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01009694 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009695 m_writer->writeAttribute( name, attribute );
9696 return *this;
9697 }
9698
9699 private:
9700 mutable XmlWriter* m_writer;
9701 };
9702
9703 XmlWriter()
9704 : m_tagIsOpen( false ),
9705 m_needsNewline( false ),
Phil Nashd08cee22017-02-13 16:15:42 +00009706 m_os( Catch::cout() )
Phil Nash40f60682016-09-27 10:46:22 +01009707 {
Phil Nashd08cee22017-02-13 16:15:42 +00009708 writeDeclaration();
Phil Nash40f60682016-09-27 10:46:22 +01009709 }
Phil Nash56d5c422012-08-23 20:08:50 +01009710
9711 XmlWriter( std::ostream& os )
9712 : m_tagIsOpen( false ),
9713 m_needsNewline( false ),
Phil Nashd08cee22017-02-13 16:15:42 +00009714 m_os( os )
Phil Nash40f60682016-09-27 10:46:22 +01009715 {
Phil Nashd08cee22017-02-13 16:15:42 +00009716 writeDeclaration();
Phil Nash40f60682016-09-27 10:46:22 +01009717 }
Phil Nash56d5c422012-08-23 20:08:50 +01009718
9719 ~XmlWriter() {
9720 while( !m_tags.empty() )
9721 endElement();
9722 }
9723
Phil Nash8defc712013-04-24 19:10:02 +01009724 XmlWriter& startElement( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009725 ensureTagClosed();
9726 newlineIfNecessary();
Phil Nashd08cee22017-02-13 16:15:42 +00009727 m_os << m_indent << '<' << name;
Phil Nash56d5c422012-08-23 20:08:50 +01009728 m_tags.push_back( name );
9729 m_indent += " ";
9730 m_tagIsOpen = true;
9731 return *this;
9732 }
9733
Phil Nash8defc712013-04-24 19:10:02 +01009734 ScopedElement scopedElement( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009735 ScopedElement scoped( this );
9736 startElement( name );
9737 return scoped;
9738 }
9739
9740 XmlWriter& endElement() {
9741 newlineIfNecessary();
9742 m_indent = m_indent.substr( 0, m_indent.size()-2 );
9743 if( m_tagIsOpen ) {
Phil Nashd08cee22017-02-13 16:15:42 +00009744 m_os << "/>";
Phil Nash56d5c422012-08-23 20:08:50 +01009745 m_tagIsOpen = false;
9746 }
9747 else {
Phil Nashd08cee22017-02-13 16:15:42 +00009748 m_os << m_indent << "</" << m_tags.back() << ">";
Phil Nash56d5c422012-08-23 20:08:50 +01009749 }
Phil Nashd08cee22017-02-13 16:15:42 +00009750 m_os << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01009751 m_tags.pop_back();
9752 return *this;
9753 }
9754
Phil Nash8defc712013-04-24 19:10:02 +01009755 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01009756 if( !name.empty() && !attribute.empty() )
Phil Nashd08cee22017-02-13 16:15:42 +00009757 m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
Phil Nash56d5c422012-08-23 20:08:50 +01009758 return *this;
9759 }
9760
Phil Nash8defc712013-04-24 19:10:02 +01009761 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
Phil Nashd08cee22017-02-13 16:15:42 +00009762 m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
Phil Nash56d5c422012-08-23 20:08:50 +01009763 return *this;
9764 }
9765
9766 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01009767 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01009768 std::ostringstream oss;
9769 oss << attribute;
9770 return writeAttribute( name, oss.str() );
Phil Nash56d5c422012-08-23 20:08:50 +01009771 }
9772
Phil Nash8defc712013-04-24 19:10:02 +01009773 XmlWriter& writeText( std::string const& text, bool indent = true ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009774 if( !text.empty() ){
9775 bool tagWasOpen = m_tagIsOpen;
9776 ensureTagClosed();
Phil Nasha1fbfea2012-12-01 23:57:18 +00009777 if( tagWasOpen && indent )
Phil Nashd08cee22017-02-13 16:15:42 +00009778 m_os << m_indent;
9779 m_os << XmlEncode( text );
Phil Nash56d5c422012-08-23 20:08:50 +01009780 m_needsNewline = true;
9781 }
9782 return *this;
9783 }
9784
Phil Nash8defc712013-04-24 19:10:02 +01009785 XmlWriter& writeComment( std::string const& text ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009786 ensureTagClosed();
Phil Nashd08cee22017-02-13 16:15:42 +00009787 m_os << m_indent << "<!--" << text << "-->";
Phil Nash56d5c422012-08-23 20:08:50 +01009788 m_needsNewline = true;
9789 return *this;
9790 }
9791
Phil Nashd08cee22017-02-13 16:15:42 +00009792 void writeStylesheetRef( std::string const& url ) {
9793 m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
9794 }
9795
Phil Nash56d5c422012-08-23 20:08:50 +01009796 XmlWriter& writeBlankLine() {
9797 ensureTagClosed();
Phil Nashd08cee22017-02-13 16:15:42 +00009798 m_os << '\n';
Phil Nash56d5c422012-08-23 20:08:50 +01009799 return *this;
9800 }
9801
Phil Nashd08cee22017-02-13 16:15:42 +00009802 void ensureTagClosed() {
9803 if( m_tagIsOpen ) {
9804 m_os << ">" << std::endl;
9805 m_tagIsOpen = false;
9806 }
Phil Nash9241e432014-05-20 18:50:59 +01009807 }
9808
Phil Nash56d5c422012-08-23 20:08:50 +01009809 private:
Phil Nash9241e432014-05-20 18:50:59 +01009810 XmlWriter( XmlWriter const& );
9811 void operator=( XmlWriter const& );
Phil Nash56d5c422012-08-23 20:08:50 +01009812
Phil Nashd08cee22017-02-13 16:15:42 +00009813 void writeDeclaration() {
9814 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
Phil Nash56d5c422012-08-23 20:08:50 +01009815 }
9816
9817 void newlineIfNecessary() {
9818 if( m_needsNewline ) {
Phil Nashd08cee22017-02-13 16:15:42 +00009819 m_os << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01009820 m_needsNewline = false;
9821 }
9822 }
9823
Phil Nash56d5c422012-08-23 20:08:50 +01009824 bool m_tagIsOpen;
9825 bool m_needsNewline;
9826 std::vector<std::string> m_tags;
9827 std::string m_indent;
Phil Nashd08cee22017-02-13 16:15:42 +00009828 std::ostream& m_os;
Phil Nash56d5c422012-08-23 20:08:50 +01009829 };
9830
9831}
Phil Nash2f6371f2015-07-23 23:06:26 +01009832// #included from: catch_reenable_warnings.h
9833
9834#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
9835
9836#ifdef __clang__
9837# ifdef __ICC // icpc defines the __clang__ macro
9838# pragma warning(pop)
9839# else
9840# pragma clang diagnostic pop
9841# endif
9842#elif defined __GNUC__
9843# pragma GCC diagnostic pop
9844#endif
9845
9846
Phil Nash56d5c422012-08-23 20:08:50 +01009847namespace Catch {
Phil Nashd76e0812014-12-30 18:26:07 +00009848 class XmlReporter : public StreamingReporterBase {
Phil Nash56d5c422012-08-23 20:08:50 +01009849 public:
Phil Nashd76e0812014-12-30 18:26:07 +00009850 XmlReporter( ReporterConfig const& _config )
9851 : StreamingReporterBase( _config ),
Phil Nash2be37272016-11-29 12:15:50 +00009852 m_xml(_config.stream()),
Phil Nashd76e0812014-12-30 18:26:07 +00009853 m_sectionDepth( 0 )
Phil Nashe73583d2015-08-07 17:30:34 +01009854 {
9855 m_reporterPrefs.shouldRedirectStdOut = true;
9856 }
Phil Nashd76e0812014-12-30 18:26:07 +00009857
Phil Nashe73583d2015-08-07 17:30:34 +01009858 virtual ~XmlReporter() CATCH_OVERRIDE;
Phil Nash56d5c422012-08-23 20:08:50 +01009859
9860 static std::string getDescription() {
9861 return "Reports test results as an XML document";
9862 }
Phil Nash56d5c422012-08-23 20:08:50 +01009863
Phil Nashd08cee22017-02-13 16:15:42 +00009864 virtual std::string getStylesheetRef() const {
9865 return std::string();
9866 }
9867
Phil Nash0952b762017-02-28 14:19:09 +00009868 void writeSourceInfo( SourceLineInfo const& sourceInfo ) {
9869 m_xml
9870 .writeAttribute( "filename", sourceInfo.file )
9871 .writeAttribute( "line", sourceInfo.line );
9872 }
9873
Phil Nashd76e0812014-12-30 18:26:07 +00009874 public: // StreamingReporterBase
Phil Nash56d5c422012-08-23 20:08:50 +01009875
Phil Nashe73583d2015-08-07 17:30:34 +01009876 virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009877 StreamingReporterBase::noMatchingTestCases( s );
9878 }
9879
Phil Nashe73583d2015-08-07 17:30:34 +01009880 virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009881 StreamingReporterBase::testRunStarting( testInfo );
Phil Nashd08cee22017-02-13 16:15:42 +00009882 std::string stylesheetRef = getStylesheetRef();
9883 if( !stylesheetRef.empty() )
9884 m_xml.writeStylesheetRef( stylesheetRef );
Phil Nash56d5c422012-08-23 20:08:50 +01009885 m_xml.startElement( "Catch" );
Phil Nashd76e0812014-12-30 18:26:07 +00009886 if( !m_config->name().empty() )
9887 m_xml.writeAttribute( "name", m_config->name() );
Phil Nash56d5c422012-08-23 20:08:50 +01009888 }
9889
Phil Nashe73583d2015-08-07 17:30:34 +01009890 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009891 StreamingReporterBase::testGroupStarting( groupInfo );
Phil Nash56d5c422012-08-23 20:08:50 +01009892 m_xml.startElement( "Group" )
Phil Nashd76e0812014-12-30 18:26:07 +00009893 .writeAttribute( "name", groupInfo.name );
Phil Nash56d5c422012-08-23 20:08:50 +01009894 }
9895
Phil Nashe73583d2015-08-07 17:30:34 +01009896 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009897 StreamingReporterBase::testCaseStarting(testInfo);
Phil Nashd08cee22017-02-13 16:15:42 +00009898 m_xml.startElement( "TestCase" )
9899 .writeAttribute( "name", trim( testInfo.name ) )
9900 .writeAttribute( "description", testInfo.description )
9901 .writeAttribute( "tags", testInfo.tagsAsString );
Phil Nashd76e0812014-12-30 18:26:07 +00009902
Phil Nash0952b762017-02-28 14:19:09 +00009903 writeSourceInfo( testInfo.lineInfo );
9904
Phil Nashd76e0812014-12-30 18:26:07 +00009905 if ( m_config->showDurations() == ShowDurations::Always )
9906 m_testCaseTimer.start();
Phil Nashd08cee22017-02-13 16:15:42 +00009907 m_xml.ensureTagClosed();
Phil Nash56d5c422012-08-23 20:08:50 +01009908 }
9909
Phil Nashe73583d2015-08-07 17:30:34 +01009910 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009911 StreamingReporterBase::sectionStarting( sectionInfo );
Phil Nash8a52a392013-07-25 08:12:03 +01009912 if( m_sectionDepth++ > 0 ) {
9913 m_xml.startElement( "Section" )
Phil Nashd76e0812014-12-30 18:26:07 +00009914 .writeAttribute( "name", trim( sectionInfo.name ) )
9915 .writeAttribute( "description", sectionInfo.description );
Phil Nash0952b762017-02-28 14:19:09 +00009916 writeSourceInfo( sectionInfo.lineInfo );
Phil Nashd08cee22017-02-13 16:15:42 +00009917 m_xml.ensureTagClosed();
Phil Nash8a52a392013-07-25 08:12:03 +01009918 }
Phil Nash56d5c422012-08-23 20:08:50 +01009919 }
9920
Phil Nashe73583d2015-08-07 17:30:34 +01009921 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
Phil Nash56d5c422012-08-23 20:08:50 +01009922
Phil Nashe73583d2015-08-07 17:30:34 +01009923 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009924 const AssertionResult& assertionResult = assertionStats.assertionResult;
Phil Nash56d5c422012-08-23 20:08:50 +01009925
Phil Nashd76e0812014-12-30 18:26:07 +00009926 // Print any info messages in <Info> tags.
9927 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
9928 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
9929 it != itEnd;
9930 ++it ) {
9931 if( it->type == ResultWas::Info ) {
9932 m_xml.scopedElement( "Info" )
9933 .writeText( it->message );
9934 } else if ( it->type == ResultWas::Warning ) {
9935 m_xml.scopedElement( "Warning" )
9936 .writeText( it->message );
9937 }
9938 }
9939 }
9940
9941 // Drop out if result was successful but we're not printing them.
9942 if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) )
9943 return true;
9944
9945 // Print the expression if there is one.
Phil Nashce612bf2012-11-01 08:27:09 +00009946 if( assertionResult.hasExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009947 m_xml.startElement( "Expression" )
Phil Nash90a35942012-11-13 22:04:29 +00009948 .writeAttribute( "success", assertionResult.succeeded() )
Phil Nash0952b762017-02-28 14:19:09 +00009949 .writeAttribute( "type", assertionResult.getTestMacroName() );
9950
9951 writeSourceInfo( assertionResult.getSourceInfo() );
Phil Nash56d5c422012-08-23 20:08:50 +01009952
9953 m_xml.scopedElement( "Original" )
Phil Nashce612bf2012-11-01 08:27:09 +00009954 .writeText( assertionResult.getExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +01009955 m_xml.scopedElement( "Expanded" )
Phil Nashce612bf2012-11-01 08:27:09 +00009956 .writeText( assertionResult.getExpandedExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +01009957 }
9958
Phil Nashd76e0812014-12-30 18:26:07 +00009959 // And... Print a result applicable to each result type.
Phil Nashce612bf2012-11-01 08:27:09 +00009960 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009961 case ResultWas::ThrewException:
Phil Nash0952b762017-02-28 14:19:09 +00009962 m_xml.startElement( "Exception" );
9963 writeSourceInfo( assertionResult.getSourceInfo() );
9964 m_xml.writeText( assertionResult.getMessage() );
9965 m_xml.endElement();
Phil Nash56d5c422012-08-23 20:08:50 +01009966 break;
Phil Nash93b61e12014-08-22 19:35:41 +01009967 case ResultWas::FatalErrorCondition:
Phil Nash0952b762017-02-28 14:19:09 +00009968 m_xml.startElement( "FatalErrorCondition" );
9969 writeSourceInfo( assertionResult.getSourceInfo() );
9970 m_xml.writeText( assertionResult.getMessage() );
9971 m_xml.endElement();
Phil Nash93b61e12014-08-22 19:35:41 +01009972 break;
Phil Nash56d5c422012-08-23 20:08:50 +01009973 case ResultWas::Info:
9974 m_xml.scopedElement( "Info" )
Phil Nashce612bf2012-11-01 08:27:09 +00009975 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01009976 break;
9977 case ResultWas::Warning:
Phil Nashd76e0812014-12-30 18:26:07 +00009978 // Warning will already have been written
Phil Nash56d5c422012-08-23 20:08:50 +01009979 break;
9980 case ResultWas::ExplicitFailure:
Phil Nash0952b762017-02-28 14:19:09 +00009981 m_xml.startElement( "Failure" );
9982 writeSourceInfo( assertionResult.getSourceInfo() );
9983 m_xml.writeText( assertionResult.getMessage() );
9984 m_xml.endElement();
Phil Nash56d5c422012-08-23 20:08:50 +01009985 break;
Phil Nashd76e0812014-12-30 18:26:07 +00009986 default:
Phil Nash56d5c422012-08-23 20:08:50 +01009987 break;
9988 }
Phil Nashd76e0812014-12-30 18:26:07 +00009989
Phil Nashce612bf2012-11-01 08:27:09 +00009990 if( assertionResult.hasExpression() )
Phil Nash56d5c422012-08-23 20:08:50 +01009991 m_xml.endElement();
Phil Nashd76e0812014-12-30 18:26:07 +00009992
9993 return true;
Phil Nash56d5c422012-08-23 20:08:50 +01009994 }
9995
Phil Nashe73583d2015-08-07 17:30:34 +01009996 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009997 StreamingReporterBase::sectionEnded( sectionStats );
9998 if( --m_sectionDepth > 0 ) {
9999 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
10000 e.writeAttribute( "successes", sectionStats.assertions.passed );
10001 e.writeAttribute( "failures", sectionStats.assertions.failed );
10002 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
10003
10004 if ( m_config->showDurations() == ShowDurations::Always )
10005 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
10006
10007 m_xml.endElement();
10008 }
Phil Nash56d5c422012-08-23 20:08:50 +010010009 }
10010
Phil Nashe73583d2015-08-07 17:30:34 +010010011 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +000010012 StreamingReporterBase::testCaseEnded( testCaseStats );
10013 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
10014 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
10015
10016 if ( m_config->showDurations() == ShowDurations::Always )
10017 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
10018
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +010010019 if( !testCaseStats.stdOut.empty() )
10020 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
10021 if( !testCaseStats.stdErr.empty() )
10022 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
10023
Phil Nashd76e0812014-12-30 18:26:07 +000010024 m_xml.endElement();
10025 }
10026
Phil Nashe73583d2015-08-07 17:30:34 +010010027 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +000010028 StreamingReporterBase::testGroupEnded( testGroupStats );
10029 // TODO: Check testGroupStats.aborting and act accordingly.
10030 m_xml.scopedElement( "OverallResults" )
10031 .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
10032 .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
10033 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
10034 m_xml.endElement();
10035 }
10036
Phil Nashe73583d2015-08-07 17:30:34 +010010037 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +000010038 StreamingReporterBase::testRunEnded( testRunStats );
10039 m_xml.scopedElement( "OverallResults" )
10040 .writeAttribute( "successes", testRunStats.totals.assertions.passed )
10041 .writeAttribute( "failures", testRunStats.totals.assertions.failed )
10042 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
Phil Nash56d5c422012-08-23 20:08:50 +010010043 m_xml.endElement();
10044 }
10045
10046 private:
Phil Nashd76e0812014-12-30 18:26:07 +000010047 Timer m_testCaseTimer;
Phil Nash56d5c422012-08-23 20:08:50 +010010048 XmlWriter m_xml;
Phil Nash8a52a392013-07-25 08:12:03 +010010049 int m_sectionDepth;
Phil Nash56d5c422012-08-23 20:08:50 +010010050 };
10051
Phil Nashd76e0812014-12-30 18:26:07 +000010052 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
10053
Phil Nash56d5c422012-08-23 20:08:50 +010010054} // end namespace Catch
10055
10056// #included from: ../reporters/catch_reporter_junit.hpp
10057#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
10058
Phil Nashf276a052012-12-02 00:05:51 +000010059#include <assert.h>
10060
Phil Nash56d5c422012-08-23 20:08:50 +010010061namespace Catch {
10062
Martin Hořeňovský9a566092017-01-20 12:49:59 +010010063 namespace {
10064 std::string getCurrentTimestamp() {
10065 // Beware, this is not reentrant because of backward compatibility issues
10066 // Also, UTC only, again because of backward compatibility (%z is C++11)
10067 time_t rawtime;
10068 std::time(&rawtime);
10069 const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z");
10070
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +010010071#ifdef _MSC_VER
Martin Hořeňovský9a566092017-01-20 12:49:59 +010010072 std::tm timeInfo = {};
10073 gmtime_s(&timeInfo, &rawtime);
10074#else
10075 std::tm* timeInfo;
10076 timeInfo = std::gmtime(&rawtime);
10077#endif
10078
10079 char timeStamp[timeStampSize];
10080 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
10081
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +010010082#ifdef _MSC_VER
Martin Hořeňovský9a566092017-01-20 12:49:59 +010010083 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
10084#else
10085 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
10086#endif
10087 return std::string(timeStamp);
10088 }
10089
10090 }
10091
Phil Nashaa7123b2013-08-15 19:01:00 +010010092 class JunitReporter : public CumulativeReporterBase {
Phil Nash56d5c422012-08-23 20:08:50 +010010093 public:
Phil Nashaa7123b2013-08-15 19:01:00 +010010094 JunitReporter( ReporterConfig const& _config )
10095 : CumulativeReporterBase( _config ),
10096 xml( _config.stream() )
Phil Nashe73583d2015-08-07 17:30:34 +010010097 {
10098 m_reporterPrefs.shouldRedirectStdOut = true;
10099 }
Phil Nashaa7123b2013-08-15 19:01:00 +010010100
Phil Nashe73583d2015-08-07 17:30:34 +010010101 virtual ~JunitReporter() CATCH_OVERRIDE;
Phil Nash56d5c422012-08-23 20:08:50 +010010102
10103 static std::string getDescription() {
10104 return "Reports test results in an XML format that looks like Ant's junitreport target";
10105 }
10106
Phil Nashe73583d2015-08-07 17:30:34 +010010107 virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {}
Phil Nash56d5c422012-08-23 20:08:50 +010010108
Phil Nashe73583d2015-08-07 17:30:34 +010010109 virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010110 CumulativeReporterBase::testRunStarting( runInfo );
10111 xml.startElement( "testsuites" );
10112 }
Phil Nash56d5c422012-08-23 20:08:50 +010010113
Phil Nashe73583d2015-08-07 17:30:34 +010010114 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010115 suiteTimer.start();
10116 stdOutForSuite.str("");
10117 stdErrForSuite.str("");
10118 unexpectedExceptions = 0;
10119 CumulativeReporterBase::testGroupStarting( groupInfo );
10120 }
10121
Phil Nashe73583d2015-08-07 17:30:34 +010010122 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010123 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
10124 unexpectedExceptions++;
10125 return CumulativeReporterBase::assertionEnded( assertionStats );
10126 }
10127
Phil Nashe73583d2015-08-07 17:30:34 +010010128 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010129 stdOutForSuite << testCaseStats.stdOut;
10130 stdErrForSuite << testCaseStats.stdErr;
10131 CumulativeReporterBase::testCaseEnded( testCaseStats );
10132 }
10133
Phil Nashe73583d2015-08-07 17:30:34 +010010134 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010135 double suiteTime = suiteTimer.getElapsedSeconds();
10136 CumulativeReporterBase::testGroupEnded( testGroupStats );
10137 writeGroup( *m_testGroups.back(), suiteTime );
10138 }
10139
Phil Nashe73583d2015-08-07 17:30:34 +010010140 virtual void testRunEndedCumulative() CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010141 xml.endElement();
10142 }
10143
10144 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
10145 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
10146 TestGroupStats const& stats = groupNode.value;
10147 xml.writeAttribute( "name", stats.groupInfo.name );
10148 xml.writeAttribute( "errors", unexpectedExceptions );
10149 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
10150 xml.writeAttribute( "tests", stats.totals.assertions.total() );
10151 xml.writeAttribute( "hostname", "tbd" ); // !TBD
10152 if( m_config->showDurations() == ShowDurations::Never )
10153 xml.writeAttribute( "time", "" );
Phil Nashef60d542012-11-16 08:47:03 +000010154 else
Phil Nashaa7123b2013-08-15 19:01:00 +010010155 xml.writeAttribute( "time", suiteTime );
Martin Hořeňovský9a566092017-01-20 12:49:59 +010010156 xml.writeAttribute( "timestamp", getCurrentTimestamp() );
Phil Nashaa7123b2013-08-15 19:01:00 +010010157
10158 // Write test cases
10159 for( TestGroupNode::ChildNodes::const_iterator
10160 it = groupNode.children.begin(), itEnd = groupNode.children.end();
10161 it != itEnd;
10162 ++it )
10163 writeTestCase( **it );
10164
10165 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
10166 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
Phil Nash56d5c422012-08-23 20:08:50 +010010167 }
10168
Phil Nashaa7123b2013-08-15 19:01:00 +010010169 void writeTestCase( TestCaseNode const& testCaseNode ) {
10170 TestCaseStats const& stats = testCaseNode.value;
10171
10172 // All test cases have exactly one section - which represents the
10173 // test case itself. That section may have 0-n nested sections
10174 assert( testCaseNode.children.size() == 1 );
10175 SectionNode const& rootSection = *testCaseNode.children.front();
10176
10177 std::string className = stats.testInfo.className;
10178
10179 if( className.empty() ) {
10180 if( rootSection.childSections.empty() )
10181 className = "global";
10182 }
10183 writeSection( className, "", rootSection );
Phil Nash56d5c422012-08-23 20:08:50 +010010184 }
10185
Phil Nashaa7123b2013-08-15 19:01:00 +010010186 void writeSection( std::string const& className,
10187 std::string const& rootName,
10188 SectionNode const& sectionNode ) {
10189 std::string name = trim( sectionNode.stats.sectionInfo.name );
10190 if( !rootName.empty() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010191 name = rootName + '/' + name;
Phil Nash56d5c422012-08-23 20:08:50 +010010192
Phil Nashaa7123b2013-08-15 19:01:00 +010010193 if( !sectionNode.assertions.empty() ||
10194 !sectionNode.stdOut.empty() ||
10195 !sectionNode.stdErr.empty() ) {
10196 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
10197 if( className.empty() ) {
10198 xml.writeAttribute( "classname", name );
10199 xml.writeAttribute( "name", "root" );
10200 }
10201 else {
10202 xml.writeAttribute( "classname", className );
10203 xml.writeAttribute( "name", name );
10204 }
Phil Nash13f98432014-12-12 08:11:18 +000010205 xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
Phil Nasha70fbe32012-08-31 08:10:36 +010010206
Phil Nashaa7123b2013-08-15 19:01:00 +010010207 writeAssertions( sectionNode );
Phil Nash56d5c422012-08-23 20:08:50 +010010208
Phil Nashaa7123b2013-08-15 19:01:00 +010010209 if( !sectionNode.stdOut.empty() )
10210 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
10211 if( !sectionNode.stdErr.empty() )
10212 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
10213 }
10214 for( SectionNode::ChildSections::const_iterator
10215 it = sectionNode.childSections.begin(),
10216 itEnd = sectionNode.childSections.end();
10217 it != itEnd;
10218 ++it )
10219 if( className.empty() )
10220 writeSection( name, "", **it );
10221 else
10222 writeSection( className, name, **it );
Phil Nash56d5c422012-08-23 20:08:50 +010010223 }
10224
Phil Nashaa7123b2013-08-15 19:01:00 +010010225 void writeAssertions( SectionNode const& sectionNode ) {
10226 for( SectionNode::Assertions::const_iterator
10227 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
10228 it != itEnd;
10229 ++it )
10230 writeAssertion( *it );
10231 }
10232 void writeAssertion( AssertionStats const& stats ) {
10233 AssertionResult const& result = stats.assertionResult;
10234 if( !result.isOk() ) {
10235 std::string elementName;
10236 switch( result.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +010010237 case ResultWas::ThrewException:
Phil Nash93b61e12014-08-22 19:35:41 +010010238 case ResultWas::FatalErrorCondition:
Phil Nashaa7123b2013-08-15 19:01:00 +010010239 elementName = "error";
Phil Nash56d5c422012-08-23 20:08:50 +010010240 break;
10241 case ResultWas::ExplicitFailure:
Phil Nashaa7123b2013-08-15 19:01:00 +010010242 elementName = "failure";
Phil Nash56d5c422012-08-23 20:08:50 +010010243 break;
10244 case ResultWas::ExpressionFailed:
Phil Nashaa7123b2013-08-15 19:01:00 +010010245 elementName = "failure";
Phil Nash56d5c422012-08-23 20:08:50 +010010246 break;
Phil Nash243f2d22013-04-12 10:43:06 +010010247 case ResultWas::DidntThrowException:
Phil Nashaa7123b2013-08-15 19:01:00 +010010248 elementName = "failure";
Phil Nash243f2d22013-04-12 10:43:06 +010010249 break;
Phil Nashaa7123b2013-08-15 19:01:00 +010010250
10251 // We should never see these here:
10252 case ResultWas::Info:
10253 case ResultWas::Warning:
10254 case ResultWas::Ok:
Phil Nash56d5c422012-08-23 20:08:50 +010010255 case ResultWas::Unknown:
10256 case ResultWas::FailureBit:
10257 case ResultWas::Exception:
Phil Nashaa7123b2013-08-15 19:01:00 +010010258 elementName = "internalError";
Phil Nash56d5c422012-08-23 20:08:50 +010010259 break;
10260 }
Phil Nashaa7123b2013-08-15 19:01:00 +010010261
10262 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
10263
10264 xml.writeAttribute( "message", result.getExpandedExpression() );
10265 xml.writeAttribute( "type", result.getTestMacroName() );
10266
10267 std::ostringstream oss;
10268 if( !result.getMessage().empty() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010269 oss << result.getMessage() << '\n';
Phil Nashaa7123b2013-08-15 19:01:00 +010010270 for( std::vector<MessageInfo>::const_iterator
10271 it = stats.infoMessages.begin(),
10272 itEnd = stats.infoMessages.end();
10273 it != itEnd;
10274 ++it )
10275 if( it->type == ResultWas::Info )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010276 oss << it->message << '\n';
Phil Nashaa7123b2013-08-15 19:01:00 +010010277
10278 oss << "at " << result.getSourceInfo();
10279 xml.writeText( oss.str(), false );
Phil Nash56d5c422012-08-23 20:08:50 +010010280 }
10281 }
10282
Phil Nashaa7123b2013-08-15 19:01:00 +010010283 XmlWriter xml;
10284 Timer suiteTimer;
10285 std::ostringstream stdOutForSuite;
10286 std::ostringstream stdErrForSuite;
10287 unsigned int unexpectedExceptions;
Phil Nash56d5c422012-08-23 20:08:50 +010010288 };
10289
Phil Nashaa7123b2013-08-15 19:01:00 +010010290 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
10291
Phil Nash56d5c422012-08-23 20:08:50 +010010292} // end namespace Catch
10293
Phil Nashff03cdf2012-12-06 08:44:51 +000010294// #included from: ../reporters/catch_reporter_console.hpp
10295#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
10296
Phil Nash0952b762017-02-28 14:19:09 +000010297#include <cfloat>
10298#include <cstdio>
10299
Phil Nashff03cdf2012-12-06 08:44:51 +000010300namespace Catch {
10301
Phil Nash0952b762017-02-28 14:19:09 +000010302 namespace {
10303 // Because formatting using c++ streams is stateful, drop down to C is required
10304 // Alternatively we could use stringstream, but its performance is... not good.
10305 std::string getFormattedDuration( double duration ) {
10306 // Max exponent + 1 is required to represent the whole part
10307 // + 1 for decimal point
10308 // + 3 for the 3 decimal places
10309 // + 1 for null terminator
10310 const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
10311 char buffer[maxDoubleSize];
10312#ifdef _MSC_VER
10313 sprintf_s(buffer, "%.3f", duration);
10314#else
10315 sprintf(buffer, "%.3f", duration);
10316#endif
10317 return std::string(buffer);
10318 }
10319 }
10320
Phil Nash2e7d9662013-01-16 09:44:43 +000010321 struct ConsoleReporter : StreamingReporterBase {
Phil Nashff03cdf2012-12-06 08:44:51 +000010322 ConsoleReporter( ReporterConfig const& _config )
Phil Nash2e7d9662013-01-16 09:44:43 +000010323 : StreamingReporterBase( _config ),
Phil Nash08e52962014-07-03 19:08:44 +010010324 m_headerPrinted( false )
Phil Nashff03cdf2012-12-06 08:44:51 +000010325 {}
10326
Phil Nashe73583d2015-08-07 17:30:34 +010010327 virtual ~ConsoleReporter() CATCH_OVERRIDE;
Phil Nashff03cdf2012-12-06 08:44:51 +000010328 static std::string getDescription() {
10329 return "Reports test results as plain lines of text";
10330 }
Phil Nashff03cdf2012-12-06 08:44:51 +000010331
Phil Nashe73583d2015-08-07 17:30:34 +010010332 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010333 stream << "No test cases matched '" << spec << '\'' << std::endl;
Phil Nash37186a12013-03-13 12:19:30 +000010334 }
10335
Phil Nashe73583d2015-08-07 17:30:34 +010010336 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
Phil Nashff03cdf2012-12-06 08:44:51 +000010337 }
Phil Nashbcad0932012-12-10 08:54:57 +000010338
Phil Nashe73583d2015-08-07 17:30:34 +010010339 virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
Phil Nash2e7d9662013-01-16 09:44:43 +000010340 AssertionResult const& result = _assertionStats.assertionResult;
Phil Nashbcad0932012-12-10 08:54:57 +000010341
Phil Nash8d44f2d2013-11-13 08:10:45 +000010342 bool printInfoMessages = true;
10343
Phil Nashbcad0932012-12-10 08:54:57 +000010344 // Drop out if result was successful and we're not printing those
Phil Nash8d44f2d2013-11-13 08:10:45 +000010345 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
10346 if( result.getResultType() != ResultWas::Warning )
10347 return false;
10348 printInfoMessages = false;
10349 }
Phil Nashbcad0932012-12-10 08:54:57 +000010350
10351 lazyPrint();
10352
Phil Nash8d44f2d2013-11-13 08:10:45 +000010353 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
Phil Nashe4756452013-01-26 20:18:30 +000010354 printer.print();
Phil Nash2e7d9662013-01-16 09:44:43 +000010355 stream << std::endl;
Phil Nashb5fd5a62013-06-28 17:09:57 +010010356 return true;
Phil Nash2e7d9662013-01-16 09:44:43 +000010357 }
10358
Phil Nashe73583d2015-08-07 17:30:34 +010010359 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
Phil Nasha04981b2013-03-08 09:30:25 +000010360 m_headerPrinted = false;
Phil Nashe4756452013-01-26 20:18:30 +000010361 StreamingReporterBase::sectionStarting( _sectionInfo );
Phil Nash2e7d9662013-01-16 09:44:43 +000010362 }
Phil Nashe73583d2015-08-07 17:30:34 +010010363 virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE {
Phil Nash2e7d9662013-01-16 09:44:43 +000010364 if( _sectionStats.missingAssertions ) {
10365 lazyPrint();
Phil Nash12c16ff2013-04-05 20:58:01 +010010366 Colour colour( Colour::ResultError );
Phil Nashaa7123b2013-08-15 19:01:00 +010010367 if( m_sectionStack.size() > 1 )
10368 stream << "\nNo assertions in section";
10369 else
10370 stream << "\nNo assertions in test case";
10371 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +000010372 }
Phil Nash0952b762017-02-28 14:19:09 +000010373 if( m_config->showDurations() == ShowDurations::Always ) {
10374 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
Phil Nash46118712013-08-16 19:01:32 +010010375 }
Phil Nash0952b762017-02-28 14:19:09 +000010376 if( m_headerPrinted ) {
10377 m_headerPrinted = false;
Phil Nashf7378ee2013-09-07 12:07:38 +010010378 }
Phil Nash2e7d9662013-01-16 09:44:43 +000010379 StreamingReporterBase::sectionEnded( _sectionStats );
10380 }
10381
Phil Nashe73583d2015-08-07 17:30:34 +010010382 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE {
Phil Nash2e7d9662013-01-16 09:44:43 +000010383 StreamingReporterBase::testCaseEnded( _testCaseStats );
Phil Nasha04981b2013-03-08 09:30:25 +000010384 m_headerPrinted = false;
Phil Nash2e7d9662013-01-16 09:44:43 +000010385 }
Phil Nashe73583d2015-08-07 17:30:34 +010010386 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010387 if( currentGroupInfo.used ) {
Phil Nash2e7d9662013-01-16 09:44:43 +000010388 printSummaryDivider();
10389 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
10390 printTotals( _testGroupStats.totals );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010391 stream << '\n' << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +000010392 }
10393 StreamingReporterBase::testGroupEnded( _testGroupStats );
10394 }
Phil Nashe73583d2015-08-07 17:30:34 +010010395 virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE {
Phil Nash52e1e742014-07-03 08:11:38 +010010396 printTotalsDivider( _testRunStats.totals );
Phil Nash2e7d9662013-01-16 09:44:43 +000010397 printTotals( _testRunStats.totals );
Phil Nash52e1e742014-07-03 08:11:38 +010010398 stream << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +000010399 StreamingReporterBase::testRunEnded( _testRunStats );
10400 }
10401
10402 private:
Phil Nashe4756452013-01-26 20:18:30 +000010403
10404 class AssertionPrinter {
Phil Nash503d5d02013-07-03 08:25:11 +010010405 void operator= ( AssertionPrinter const& );
Phil Nashe4756452013-01-26 20:18:30 +000010406 public:
Phil Nash8d44f2d2013-11-13 08:10:45 +000010407 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
Phil Nashe4756452013-01-26 20:18:30 +000010408 : stream( _stream ),
10409 stats( _stats ),
10410 result( _stats.assertionResult ),
Phil Nash12c16ff2013-04-05 20:58:01 +010010411 colour( Colour::None ),
Phil Nasha2773812013-02-02 20:37:58 +000010412 message( result.getMessage() ),
Phil Nash8d44f2d2013-11-13 08:10:45 +000010413 messages( _stats.infoMessages ),
10414 printInfoMessages( _printInfoMessages )
Phil Nashe4756452013-01-26 20:18:30 +000010415 {
10416 switch( result.getResultType() ) {
10417 case ResultWas::Ok:
Phil Nash12c16ff2013-04-05 20:58:01 +010010418 colour = Colour::Success;
Phil Nashe4756452013-01-26 20:18:30 +000010419 passOrFail = "PASSED";
Phil Nasha2773812013-02-02 20:37:58 +000010420 //if( result.hasMessage() )
10421 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +000010422 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +000010423 if( _stats.infoMessages.size() > 1 )
10424 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +000010425 break;
10426 case ResultWas::ExpressionFailed:
10427 if( result.isOk() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +010010428 colour = Colour::Success;
Phil Nashe4756452013-01-26 20:18:30 +000010429 passOrFail = "FAILED - but was ok";
10430 }
10431 else {
Phil Nash12c16ff2013-04-05 20:58:01 +010010432 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +000010433 passOrFail = "FAILED";
10434 }
Phil Nasha2773812013-02-02 20:37:58 +000010435 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +000010436 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +000010437 if( _stats.infoMessages.size() > 1 )
10438 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +000010439 break;
10440 case ResultWas::ThrewException:
Phil Nash12c16ff2013-04-05 20:58:01 +010010441 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +000010442 passOrFail = "FAILED";
10443 messageLabel = "due to unexpected exception with message";
10444 break;
Phil Nash93b61e12014-08-22 19:35:41 +010010445 case ResultWas::FatalErrorCondition:
10446 colour = Colour::Error;
10447 passOrFail = "FAILED";
10448 messageLabel = "due to a fatal error condition";
10449 break;
Phil Nashe4756452013-01-26 20:18:30 +000010450 case ResultWas::DidntThrowException:
Phil Nash12c16ff2013-04-05 20:58:01 +010010451 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +000010452 passOrFail = "FAILED";
10453 messageLabel = "because no exception was thrown where one was expected";
10454 break;
10455 case ResultWas::Info:
10456 messageLabel = "info";
10457 break;
10458 case ResultWas::Warning:
10459 messageLabel = "warning";
10460 break;
10461 case ResultWas::ExplicitFailure:
10462 passOrFail = "FAILED";
Phil Nash12c16ff2013-04-05 20:58:01 +010010463 colour = Colour::Error;
Phil Nasha2773812013-02-02 20:37:58 +000010464 if( _stats.infoMessages.size() == 1 )
10465 messageLabel = "explicitly with message";
10466 if( _stats.infoMessages.size() > 1 )
10467 messageLabel = "explicitly with messages";
Phil Nashe4756452013-01-26 20:18:30 +000010468 break;
Phil Nashe4756452013-01-26 20:18:30 +000010469 // These cases are here to prevent compiler warnings
10470 case ResultWas::Unknown:
10471 case ResultWas::FailureBit:
Phil Nash243f2d22013-04-12 10:43:06 +010010472 case ResultWas::Exception:
Phil Nashe4756452013-01-26 20:18:30 +000010473 passOrFail = "** internal error **";
Phil Nash12c16ff2013-04-05 20:58:01 +010010474 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +000010475 break;
10476 }
10477 }
10478
10479 void print() const {
Phil Nash767f1582013-03-04 12:19:15 +010010480 printSourceInfo();
Phil Nashe4756452013-01-26 20:18:30 +000010481 if( stats.totals.assertions.total() > 0 ) {
Phil Nash767f1582013-03-04 12:19:15 +010010482 if( result.isOk() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010483 stream << '\n';
Phil Nashe4756452013-01-26 20:18:30 +000010484 printResultType();
10485 printOriginalExpression();
10486 printReconstructedExpression();
10487 }
Phil Nash767f1582013-03-04 12:19:15 +010010488 else {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010489 stream << '\n';
Phil Nash767f1582013-03-04 12:19:15 +010010490 }
Phil Nashe4756452013-01-26 20:18:30 +000010491 printMessage();
Phil Nashe4756452013-01-26 20:18:30 +000010492 }
10493
10494 private:
10495 void printResultType() const {
10496 if( !passOrFail.empty() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +010010497 Colour colourGuard( colour );
Phil Nashe4756452013-01-26 20:18:30 +000010498 stream << passOrFail << ":\n";
10499 }
10500 }
10501 void printOriginalExpression() const {
10502 if( result.hasExpression() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +010010503 Colour colourGuard( Colour::OriginalExpression );
Phil Nashe4756452013-01-26 20:18:30 +000010504 stream << " ";
Phil Nash786959d2013-06-07 19:07:50 +010010505 stream << result.getExpressionInMacro();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010506 stream << '\n';
Phil Nashe4756452013-01-26 20:18:30 +000010507 }
10508 }
10509 void printReconstructedExpression() const {
10510 if( result.hasExpandedExpression() ) {
10511 stream << "with expansion:\n";
Phil Nash12c16ff2013-04-05 20:58:01 +010010512 Colour colourGuard( Colour::ReconstructedExpression );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010513 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n';
Phil Nashe4756452013-01-26 20:18:30 +000010514 }
10515 }
10516 void printMessage() const {
10517 if( !messageLabel.empty() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010518 stream << messageLabel << ':' << '\n';
Phil Nasha2773812013-02-02 20:37:58 +000010519 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
10520 it != itEnd;
10521 ++it ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +000010522 // If this assertion is a warning ignore any INFO messages
10523 if( printInfoMessages || it->type != ResultWas::Info )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010524 stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n';
Phil Nasha2773812013-02-02 20:37:58 +000010525 }
Phil Nashe4756452013-01-26 20:18:30 +000010526 }
10527 void printSourceInfo() const {
Phil Nash12c16ff2013-04-05 20:58:01 +010010528 Colour colourGuard( Colour::FileName );
Phil Nash767f1582013-03-04 12:19:15 +010010529 stream << result.getSourceInfo() << ": ";
Phil Nashe4756452013-01-26 20:18:30 +000010530 }
10531
Phil Nashe4756452013-01-26 20:18:30 +000010532 std::ostream& stream;
10533 AssertionStats const& stats;
10534 AssertionResult const& result;
Phil Nash12c16ff2013-04-05 20:58:01 +010010535 Colour::Code colour;
Phil Nashe4756452013-01-26 20:18:30 +000010536 std::string passOrFail;
10537 std::string messageLabel;
10538 std::string message;
Phil Nasha2773812013-02-02 20:37:58 +000010539 std::vector<MessageInfo> messages;
Phil Nash8d44f2d2013-11-13 08:10:45 +000010540 bool printInfoMessages;
Phil Nashe4756452013-01-26 20:18:30 +000010541 };
Phil Nash2e7d9662013-01-16 09:44:43 +000010542
10543 void lazyPrint() {
10544
Phil Nashaa7123b2013-08-15 19:01:00 +010010545 if( !currentTestRunInfo.used )
Phil Nash2e7d9662013-01-16 09:44:43 +000010546 lazyPrintRunInfo();
Phil Nashaa7123b2013-08-15 19:01:00 +010010547 if( !currentGroupInfo.used )
Phil Nash2e7d9662013-01-16 09:44:43 +000010548 lazyPrintGroupInfo();
Phil Nash2e7d9662013-01-16 09:44:43 +000010549
Phil Nasha04981b2013-03-08 09:30:25 +000010550 if( !m_headerPrinted ) {
10551 printTestCaseAndSectionHeader();
10552 m_headerPrinted = true;
10553 }
Phil Nash2e7d9662013-01-16 09:44:43 +000010554 }
10555 void lazyPrintRunInfo() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010556 stream << '\n' << getLineOfChars<'~'>() << '\n';
Phil Nash12c16ff2013-04-05 20:58:01 +010010557 Colour colour( Colour::SecondaryText );
Phil Nashaa7123b2013-08-15 19:01:00 +010010558 stream << currentTestRunInfo->name
Phil Nash21f7ef62015-06-29 18:05:23 +010010559 << " is a Catch v" << libraryVersion << " host application.\n"
Phil Nash2e7d9662013-01-16 09:44:43 +000010560 << "Run with -? for options\n\n";
10561
Phil Nash6a8e8ad2014-09-15 18:40:24 +010010562 if( m_config->rngSeed() != 0 )
10563 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
10564
Phil Nashaa7123b2013-08-15 19:01:00 +010010565 currentTestRunInfo.used = true;
Phil Nash2e7d9662013-01-16 09:44:43 +000010566 }
10567 void lazyPrintGroupInfo() {
Phil Nashaa7123b2013-08-15 19:01:00 +010010568 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
10569 printClosedHeader( "Group: " + currentGroupInfo->name );
10570 currentGroupInfo.used = true;
Phil Nash2e7d9662013-01-16 09:44:43 +000010571 }
10572 }
Phil Nasha04981b2013-03-08 09:30:25 +000010573 void printTestCaseAndSectionHeader() {
Phil Nashaa7123b2013-08-15 19:01:00 +010010574 assert( !m_sectionStack.empty() );
10575 printOpenHeader( currentTestCaseInfo->name );
Phil Nash2e7d9662013-01-16 09:44:43 +000010576
Phil Nashaa7123b2013-08-15 19:01:00 +010010577 if( m_sectionStack.size() > 1 ) {
10578 Colour colourGuard( Colour::Headers );
10579
10580 std::vector<SectionInfo>::const_iterator
10581 it = m_sectionStack.begin()+1, // Skip first section (test case)
10582 itEnd = m_sectionStack.end();
10583 for( ; it != itEnd; ++it )
10584 printHeaderString( it->name, 2 );
Phil Nash2e7d9662013-01-16 09:44:43 +000010585 }
Phil Nashaa7123b2013-08-15 19:01:00 +010010586
Phil Nashd08cee22017-02-13 16:15:42 +000010587 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
Phil Nash19279252013-04-20 21:07:32 +010010588
10589 if( !lineInfo.empty() ){
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010590 stream << getLineOfChars<'-'>() << '\n';
Phil Nash19279252013-04-20 21:07:32 +010010591 Colour colourGuard( Colour::FileName );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010592 stream << lineInfo << '\n';
Phil Nash19279252013-04-20 21:07:32 +010010593 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010594 stream << getLineOfChars<'.'>() << '\n' << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +000010595 }
10596
Phil Nasha04981b2013-03-08 09:30:25 +000010597 void printClosedHeader( std::string const& _name ) {
10598 printOpenHeader( _name );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010599 stream << getLineOfChars<'.'>() << '\n';
Phil Nasha04981b2013-03-08 09:30:25 +000010600 }
Phil Nash19279252013-04-20 21:07:32 +010010601 void printOpenHeader( std::string const& _name ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010602 stream << getLineOfChars<'-'>() << '\n';
Phil Nash5c7d3d72013-04-01 11:27:10 +010010603 {
Phil Nash12c16ff2013-04-05 20:58:01 +010010604 Colour colourGuard( Colour::Headers );
Phil Nash19279252013-04-20 21:07:32 +010010605 printHeaderString( _name );
Phil Nash5c7d3d72013-04-01 11:27:10 +010010606 }
Phil Nash2e7d9662013-01-16 09:44:43 +000010607 }
10608
Phil Nash12c16ff2013-04-05 20:58:01 +010010609 // if string has a : in first line will set indent to follow it on
10610 // subsequent lines
Phil Nash19279252013-04-20 21:07:32 +010010611 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
Phil Nash12c16ff2013-04-05 20:58:01 +010010612 std::size_t i = _string.find( ": " );
10613 if( i != std::string::npos )
10614 i+=2;
10615 else
10616 i = 0;
Phil Nash19279252013-04-20 21:07:32 +010010617 stream << Text( _string, TextAttributes()
10618 .setIndent( indent+i)
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010619 .setInitialIndent( indent ) ) << '\n';
Phil Nash12c16ff2013-04-05 20:58:01 +010010620 }
10621
Phil Nash28c2e072014-07-09 19:22:49 +010010622 struct SummaryColumn {
10623
10624 SummaryColumn( std::string const& _label, Colour::Code _colour )
10625 : label( _label ),
10626 colour( _colour )
10627 {}
10628 SummaryColumn addRow( std::size_t count ) {
10629 std::ostringstream oss;
10630 oss << count;
10631 std::string row = oss.str();
10632 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
10633 while( it->size() < row.size() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010634 *it = ' ' + *it;
Phil Nash28c2e072014-07-09 19:22:49 +010010635 while( it->size() > row.size() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010636 row = ' ' + row;
Phil Nash28c2e072014-07-09 19:22:49 +010010637 }
10638 rows.push_back( row );
10639 return *this;
10640 }
10641
10642 std::string label;
10643 Colour::Code colour;
10644 std::vector<std::string> rows;
10645
10646 };
10647
Phil Nash52e1e742014-07-03 08:11:38 +010010648 void printTotals( Totals const& totals ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +000010649 if( totals.testCases.total() == 0 ) {
Phil Nash52e1e742014-07-03 08:11:38 +010010650 stream << Colour( Colour::Warning ) << "No tests ran\n";
Phil Nash2e7d9662013-01-16 09:44:43 +000010651 }
Phil Nashc984fc32016-03-15 07:24:26 +000010652 else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
Phil Nash52e1e742014-07-03 08:11:38 +010010653 stream << Colour( Colour::ResultSuccess ) << "All tests passed";
10654 stream << " ("
Phil Nash2e7d9662013-01-16 09:44:43 +000010655 << pluralise( totals.assertions.passed, "assertion" ) << " in "
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010656 << pluralise( totals.testCases.passed, "test case" ) << ')'
10657 << '\n';
Phil Nashbcad0932012-12-10 08:54:57 +000010658 }
Phil Nash28c2e072014-07-09 19:22:49 +010010659 else {
Phil Nash52e1e742014-07-03 08:11:38 +010010660
Phil Nash28c2e072014-07-09 19:22:49 +010010661 std::vector<SummaryColumn> columns;
10662 columns.push_back( SummaryColumn( "", Colour::None )
10663 .addRow( totals.testCases.total() )
10664 .addRow( totals.assertions.total() ) );
10665 columns.push_back( SummaryColumn( "passed", Colour::Success )
10666 .addRow( totals.testCases.passed )
10667 .addRow( totals.assertions.passed ) );
10668 columns.push_back( SummaryColumn( "failed", Colour::ResultError )
10669 .addRow( totals.testCases.failed )
10670 .addRow( totals.assertions.failed ) );
10671 columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
10672 .addRow( totals.testCases.failedButOk )
10673 .addRow( totals.assertions.failedButOk ) );
Phil Nash52e1e742014-07-03 08:11:38 +010010674
Phil Nash28c2e072014-07-09 19:22:49 +010010675 printSummaryRow( "test cases", columns, 0 );
10676 printSummaryRow( "assertions", columns, 1 );
Phil Nashf1178122012-12-11 09:03:14 +000010677 }
Phil Nash28c2e072014-07-09 19:22:49 +010010678 }
10679 void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) {
10680 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
10681 std::string value = it->rows[row];
10682 if( it->label.empty() ) {
10683 stream << label << ": ";
10684 if( value != "0" )
10685 stream << value;
10686 else
10687 stream << Colour( Colour::Warning ) << "- none -";
10688 }
10689 else if( value != "0" ) {
10690 stream << Colour( Colour::LightGrey ) << " | ";
10691 stream << Colour( it->colour )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010692 << value << ' ' << it->label;
Phil Nash28c2e072014-07-09 19:22:49 +010010693 }
10694 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010695 stream << '\n';
Phil Nashff03cdf2012-12-06 08:44:51 +000010696 }
10697
Phil Nash52e1e742014-07-03 08:11:38 +010010698 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
10699 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
10700 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
10701 }
10702 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
10703 if( i > j && i > k )
10704 return i;
10705 else if( j > k )
10706 return j;
10707 else
10708 return k;
10709 }
10710
10711 void printTotalsDivider( Totals const& totals ) {
10712 if( totals.testCases.total() > 0 ) {
10713 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
10714 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
10715 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
10716 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
10717 findMax( failedRatio, failedButOkRatio, passedRatio )++;
10718 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
10719 findMax( failedRatio, failedButOkRatio, passedRatio )--;
10720
Phil Nash52e1e742014-07-03 08:11:38 +010010721 stream << Colour( Colour::Error ) << std::string( failedRatio, '=' );
10722 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' );
Phil Nash28c2e072014-07-09 19:22:49 +010010723 if( totals.testCases.allPassed() )
10724 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' );
10725 else
10726 stream << Colour( Colour::Success ) << std::string( passedRatio, '=' );
Phil Nash52e1e742014-07-03 08:11:38 +010010727 }
10728 else {
10729 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
10730 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010731 stream << '\n';
Phil Nashff03cdf2012-12-06 08:44:51 +000010732 }
Phil Nash2e7d9662013-01-16 09:44:43 +000010733 void printSummaryDivider() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010734 stream << getLineOfChars<'-'>() << '\n';
Phil Nashff03cdf2012-12-06 08:44:51 +000010735 }
Phil Nashff03cdf2012-12-06 08:44:51 +000010736
Phil Nashcf5ced52012-12-14 07:50:08 +000010737 private:
Phil Nasha04981b2013-03-08 09:30:25 +000010738 bool m_headerPrinted;
Phil Nashff03cdf2012-12-06 08:44:51 +000010739 };
10740
10741 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
10742
10743} // end namespace Catch
10744
Phil Nash5a2df712014-05-01 19:07:02 +010010745// #included from: ../reporters/catch_reporter_compact.hpp
10746#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
10747
10748namespace Catch {
10749
10750 struct CompactReporter : StreamingReporterBase {
10751
10752 CompactReporter( ReporterConfig const& _config )
10753 : StreamingReporterBase( _config )
10754 {}
10755
10756 virtual ~CompactReporter();
10757
10758 static std::string getDescription() {
10759 return "Reports test results on a single line, suitable for IDEs";
10760 }
10761
10762 virtual ReporterPreferences getPreferences() const {
10763 ReporterPreferences prefs;
10764 prefs.shouldRedirectStdOut = false;
10765 return prefs;
10766 }
10767
10768 virtual void noMatchingTestCases( std::string const& spec ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010769 stream << "No test cases matched '" << spec << '\'' << std::endl;
Phil Nash5a2df712014-05-01 19:07:02 +010010770 }
10771
10772 virtual void assertionStarting( AssertionInfo const& ) {
10773 }
10774
10775 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
10776 AssertionResult const& result = _assertionStats.assertionResult;
10777
10778 bool printInfoMessages = true;
10779
10780 // Drop out if result was successful and we're not printing those
10781 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
10782 if( result.getResultType() != ResultWas::Warning )
10783 return false;
10784 printInfoMessages = false;
10785 }
10786
10787 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
10788 printer.print();
10789
10790 stream << std::endl;
10791 return true;
10792 }
10793
10794 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
10795 printTotals( _testRunStats.totals );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010796 stream << '\n' << std::endl;
Phil Nash5a2df712014-05-01 19:07:02 +010010797 StreamingReporterBase::testRunEnded( _testRunStats );
10798 }
10799
10800 private:
10801 class AssertionPrinter {
10802 void operator= ( AssertionPrinter const& );
10803 public:
10804 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
10805 : stream( _stream )
10806 , stats( _stats )
10807 , result( _stats.assertionResult )
10808 , messages( _stats.infoMessages )
10809 , itMessage( _stats.infoMessages.begin() )
10810 , printInfoMessages( _printInfoMessages )
10811 {}
10812
10813 void print() {
10814 printSourceInfo();
10815
10816 itMessage = messages.begin();
10817
10818 switch( result.getResultType() ) {
10819 case ResultWas::Ok:
10820 printResultType( Colour::ResultSuccess, passedString() );
10821 printOriginalExpression();
10822 printReconstructedExpression();
10823 if ( ! result.hasExpression() )
10824 printRemainingMessages( Colour::None );
10825 else
10826 printRemainingMessages();
10827 break;
10828 case ResultWas::ExpressionFailed:
10829 if( result.isOk() )
10830 printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
10831 else
10832 printResultType( Colour::Error, failedString() );
10833 printOriginalExpression();
10834 printReconstructedExpression();
10835 printRemainingMessages();
10836 break;
10837 case ResultWas::ThrewException:
10838 printResultType( Colour::Error, failedString() );
10839 printIssue( "unexpected exception with message:" );
10840 printMessage();
10841 printExpressionWas();
10842 printRemainingMessages();
10843 break;
Phil Nash93b61e12014-08-22 19:35:41 +010010844 case ResultWas::FatalErrorCondition:
10845 printResultType( Colour::Error, failedString() );
10846 printIssue( "fatal error condition with message:" );
10847 printMessage();
10848 printExpressionWas();
10849 printRemainingMessages();
10850 break;
Phil Nash5a2df712014-05-01 19:07:02 +010010851 case ResultWas::DidntThrowException:
10852 printResultType( Colour::Error, failedString() );
10853 printIssue( "expected exception, got none" );
10854 printExpressionWas();
10855 printRemainingMessages();
10856 break;
10857 case ResultWas::Info:
10858 printResultType( Colour::None, "info" );
10859 printMessage();
10860 printRemainingMessages();
10861 break;
10862 case ResultWas::Warning:
10863 printResultType( Colour::None, "warning" );
10864 printMessage();
10865 printRemainingMessages();
10866 break;
10867 case ResultWas::ExplicitFailure:
10868 printResultType( Colour::Error, failedString() );
10869 printIssue( "explicitly" );
10870 printRemainingMessages( Colour::None );
10871 break;
10872 // These cases are here to prevent compiler warnings
10873 case ResultWas::Unknown:
10874 case ResultWas::FailureBit:
10875 case ResultWas::Exception:
10876 printResultType( Colour::Error, "** internal error **" );
10877 break;
10878 }
10879 }
10880
10881 private:
10882 // Colour::LightGrey
10883
Phil Nash9241e432014-05-20 18:50:59 +010010884 static Colour::Code dimColour() { return Colour::FileName; }
Phil Nash5a2df712014-05-01 19:07:02 +010010885
10886#ifdef CATCH_PLATFORM_MAC
10887 static const char* failedString() { return "FAILED"; }
10888 static const char* passedString() { return "PASSED"; }
10889#else
10890 static const char* failedString() { return "failed"; }
10891 static const char* passedString() { return "passed"; }
10892#endif
10893
10894 void printSourceInfo() const {
10895 Colour colourGuard( Colour::FileName );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010896 stream << result.getSourceInfo() << ':';
Phil Nash5a2df712014-05-01 19:07:02 +010010897 }
10898
Phil Nash9241e432014-05-20 18:50:59 +010010899 void printResultType( Colour::Code colour, std::string passOrFail ) const {
Phil Nash5a2df712014-05-01 19:07:02 +010010900 if( !passOrFail.empty() ) {
10901 {
10902 Colour colourGuard( colour );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010903 stream << ' ' << passOrFail;
Phil Nash5a2df712014-05-01 19:07:02 +010010904 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010905 stream << ':';
Phil Nash5a2df712014-05-01 19:07:02 +010010906 }
10907 }
10908
10909 void printIssue( std::string issue ) const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010910 stream << ' ' << issue;
Phil Nash5a2df712014-05-01 19:07:02 +010010911 }
10912
10913 void printExpressionWas() {
10914 if( result.hasExpression() ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010915 stream << ';';
Phil Nash5a2df712014-05-01 19:07:02 +010010916 {
10917 Colour colour( dimColour() );
10918 stream << " expression was:";
10919 }
10920 printOriginalExpression();
10921 }
10922 }
10923
10924 void printOriginalExpression() const {
10925 if( result.hasExpression() ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010926 stream << ' ' << result.getExpression();
Phil Nash5a2df712014-05-01 19:07:02 +010010927 }
10928 }
10929
10930 void printReconstructedExpression() const {
10931 if( result.hasExpandedExpression() ) {
10932 {
10933 Colour colour( dimColour() );
10934 stream << " for: ";
10935 }
10936 stream << result.getExpandedExpression();
10937 }
10938 }
10939
10940 void printMessage() {
10941 if ( itMessage != messages.end() ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010942 stream << " '" << itMessage->message << '\'';
Phil Nash5a2df712014-05-01 19:07:02 +010010943 ++itMessage;
10944 }
10945 }
10946
Phil Nash9241e432014-05-20 18:50:59 +010010947 void printRemainingMessages( Colour::Code colour = dimColour() ) {
Phil Nash5a2df712014-05-01 19:07:02 +010010948 if ( itMessage == messages.end() )
10949 return;
10950
10951 // using messages.end() directly yields compilation error:
10952 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
10953 const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
10954
10955 {
10956 Colour colourGuard( colour );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010957 stream << " with " << pluralise( N, "message" ) << ':';
Phil Nash5a2df712014-05-01 19:07:02 +010010958 }
10959
10960 for(; itMessage != itEnd; ) {
10961 // If this assertion is a warning ignore any INFO messages
10962 if( printInfoMessages || itMessage->type != ResultWas::Info ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010963 stream << " '" << itMessage->message << '\'';
Phil Nash5a2df712014-05-01 19:07:02 +010010964 if ( ++itMessage != itEnd ) {
10965 Colour colourGuard( dimColour() );
10966 stream << " and";
10967 }
10968 }
10969 }
10970 }
10971
10972 private:
10973 std::ostream& stream;
10974 AssertionStats const& stats;
10975 AssertionResult const& result;
10976 std::vector<MessageInfo> messages;
10977 std::vector<MessageInfo>::const_iterator itMessage;
10978 bool printInfoMessages;
10979 };
10980
10981 // Colour, message variants:
10982 // - white: No tests ran.
10983 // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
10984 // - white: Passed [both/all] N test cases (no assertions).
10985 // - red: Failed N tests cases, failed M assertions.
10986 // - green: Passed [both/all] N tests cases with M assertions.
10987
10988 std::string bothOrAll( std::size_t count ) const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010989 return count == 1 ? std::string() : count == 2 ? "both " : "all " ;
Phil Nash5a2df712014-05-01 19:07:02 +010010990 }
10991
10992 void printTotals( const Totals& totals ) const {
10993 if( totals.testCases.total() == 0 ) {
10994 stream << "No tests ran.";
10995 }
10996 else if( totals.testCases.failed == totals.testCases.total() ) {
10997 Colour colour( Colour::ResultError );
10998 const std::string qualify_assertions_failed =
10999 totals.assertions.failed == totals.assertions.total() ?
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011000 bothOrAll( totals.assertions.failed ) : std::string();
Phil Nash5a2df712014-05-01 19:07:02 +010011001 stream <<
11002 "Failed " << bothOrAll( totals.testCases.failed )
11003 << pluralise( totals.testCases.failed, "test case" ) << ", "
11004 "failed " << qualify_assertions_failed <<
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011005 pluralise( totals.assertions.failed, "assertion" ) << '.';
Phil Nash5a2df712014-05-01 19:07:02 +010011006 }
11007 else if( totals.assertions.total() == 0 ) {
11008 stream <<
11009 "Passed " << bothOrAll( totals.testCases.total() )
11010 << pluralise( totals.testCases.total(), "test case" )
11011 << " (no assertions).";
11012 }
11013 else if( totals.assertions.failed ) {
11014 Colour colour( Colour::ResultError );
11015 stream <<
11016 "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011017 "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.';
Phil Nash5a2df712014-05-01 19:07:02 +010011018 }
11019 else {
11020 Colour colour( Colour::ResultSuccess );
11021 stream <<
11022 "Passed " << bothOrAll( totals.testCases.passed )
11023 << pluralise( totals.testCases.passed, "test case" ) <<
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011024 " with " << pluralise( totals.assertions.passed, "assertion" ) << '.';
Phil Nash5a2df712014-05-01 19:07:02 +010011025 }
11026 }
11027 };
11028
11029 INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
11030
11031} // end namespace Catch
11032
Phil Nasha695eb92012-08-13 07:46:10 +010011033namespace Catch {
Phil Nash7e346192015-11-03 08:00:43 +000011034 // These are all here to avoid warnings about not having any out of line
11035 // virtual methods
Phil Nasha695eb92012-08-13 07:46:10 +010011036 NonCopyable::~NonCopyable() {}
11037 IShared::~IShared() {}
Phil Nash7e346192015-11-03 08:00:43 +000011038 IStream::~IStream() CATCH_NOEXCEPT {}
Phil Nashece529a2015-11-03 17:37:43 +000011039 FileStream::~FileStream() CATCH_NOEXCEPT {}
11040 CoutStream::~CoutStream() CATCH_NOEXCEPT {}
11041 DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
Phil Nashd7e17902014-04-18 08:49:35 +010011042 StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
Phil Nasha695eb92012-08-13 07:46:10 +010011043 IContext::~IContext() {}
11044 IResultCapture::~IResultCapture() {}
11045 ITestCase::~ITestCase() {}
11046 ITestCaseRegistry::~ITestCaseRegistry() {}
11047 IRegistryHub::~IRegistryHub() {}
11048 IMutableRegistryHub::~IMutableRegistryHub() {}
11049 IExceptionTranslator::~IExceptionTranslator() {}
11050 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
11051 IReporter::~IReporter() {}
11052 IReporterFactory::~IReporterFactory() {}
11053 IReporterRegistry::~IReporterRegistry() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +000011054 IStreamingReporter::~IStreamingReporter() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +000011055 AssertionStats::~AssertionStats() {}
11056 SectionStats::~SectionStats() {}
11057 TestCaseStats::~TestCaseStats() {}
11058 TestGroupStats::~TestGroupStats() {}
11059 TestRunStats::~TestRunStats() {}
Phil Nashaa7123b2013-08-15 19:01:00 +010011060 CumulativeReporterBase::SectionNode::~SectionNode() {}
11061 CumulativeReporterBase::~CumulativeReporterBase() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +000011062
Phil Nash2e7d9662013-01-16 09:44:43 +000011063 StreamingReporterBase::~StreamingReporterBase() {}
Phil Nashff03cdf2012-12-06 08:44:51 +000011064 ConsoleReporter::~ConsoleReporter() {}
Phil Nash5a2df712014-05-01 19:07:02 +010011065 CompactReporter::~CompactReporter() {}
Phil Nasha695eb92012-08-13 07:46:10 +010011066 IRunner::~IRunner() {}
11067 IMutableContext::~IMutableContext() {}
11068 IConfig::~IConfig() {}
11069 XmlReporter::~XmlReporter() {}
11070 JunitReporter::~JunitReporter() {}
11071 TestRegistry::~TestRegistry() {}
11072 FreeFunctionTestCase::~FreeFunctionTestCase() {}
11073 IGeneratorInfo::~IGeneratorInfo() {}
11074 IGeneratorsForTest::~IGeneratorsForTest() {}
Phil Nash8342ae82015-07-13 15:03:26 +010011075 WildcardPattern::~WildcardPattern() {}
Phil Nash65cc14c2014-05-16 18:54:48 +010011076 TestSpec::Pattern::~Pattern() {}
11077 TestSpec::NamePattern::~NamePattern() {}
11078 TestSpec::TagPattern::~TagPattern() {}
11079 TestSpec::ExcludedPattern::~ExcludedPattern() {}
Phil Nasha695eb92012-08-13 07:46:10 +010011080
11081 void Config::dummy() {}
Phil Nash7e346192015-11-03 08:00:43 +000011082
11083 namespace TestCaseTracking {
11084 ITracker::~ITracker() {}
11085 TrackerBase::~TrackerBase() {}
11086 SectionTracker::~SectionTracker() {}
11087 IndexTracker::~IndexTracker() {}
11088 }
Phil Nasha695eb92012-08-13 07:46:10 +010011089}
11090
Phil Nash5bc030d2012-08-16 18:48:50 +010011091#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +010011092#pragma clang diagnostic pop
Phil Nash89d1e6c2011-05-24 08:23:02 +010011093#endif
Matt Wozniskif29c8982012-09-17 01:42:29 -040011094
Phil Nash9abb2762014-03-06 21:53:34 +000011095#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010011096
Phil Nashde49ec42013-12-04 20:25:14 +000011097#ifdef CATCH_CONFIG_MAIN
Phil Nash89d1e6c2011-05-24 08:23:02 +010011098// #included from: internal/catch_default_main.hpp
Phil Nash3b80af72012-08-09 07:47:30 +010011099#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010011100
Phil Nash176eb812012-05-11 08:17:16 +010011101#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +010011102
Phil Nash176eb812012-05-11 08:17:16 +010011103// Standard C/C++ main entry point
Phil Nash981347b2015-12-09 18:11:48 +000011104int main (int argc, char * argv[]) {
Phil Nash0952b762017-02-28 14:19:09 +000011105 int result = Catch::Session().run( argc, argv );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011106 return ( result < 0xff ? result : 0xff );
Phil Nash176eb812012-05-11 08:17:16 +010011107}
11108
11109#else // __OBJC__
11110
11111// Objective-C entry point
11112int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +000011113#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +010011114 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +000011115#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010011116
11117 Catch::registerTestMethods();
Phil Nash786959d2013-06-07 19:07:50 +010011118 int result = Catch::Session().run( argc, (char* const*)argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +010011119
Phil Nash53c990a2012-03-17 18:20:06 +000011120#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +010011121 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +000011122#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010011123
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011124 return ( result < 0xff ? result : 0xff );
Phil Nash89d1e6c2011-05-24 08:23:02 +010011125}
11126
Phil Nash176eb812012-05-11 08:17:16 +010011127#endif // __OBJC__
11128
Phil Nash9abb2762014-03-06 21:53:34 +000011129#endif
11130
11131#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
11132# undef CLARA_CONFIG_MAIN
11133#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010011134
Phil Nash89d1e6c2011-05-24 08:23:02 +010011135//////
11136
Phil Nash46bcd4b2012-07-20 18:43:48 +010011137// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
11138#ifdef CATCH_CONFIG_PREFIX_ALL
11139
Phil Nash90a35942012-11-13 22:04:29 +000011140#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
Phil Nashab036682014-06-02 07:48:03 +010011141#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011142
Phil Nash93a842e2015-07-13 06:36:07 +010011143#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
Phil Nash90a35942012-11-13 22:04:29 +000011144#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
Phil Nash5bbdc8f2015-07-15 23:03:11 +010011145#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" )
Phil Nash90a35942012-11-13 22:04:29 +000011146#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011147
Phil Nash90a35942012-11-13 22:04:29 +000011148#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
Phil Nashab036682014-06-02 07:48:03 +010011149#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" )
Phil Nash90a35942012-11-13 22:04:29 +000011150#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
11151#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
11152#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011153
Phil Nash3b2f2062017-01-11 16:43:56 +000011154#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CATCH_CHECK_THROWS" )
Phil Nash90a35942012-11-13 22:04:29 +000011155#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
Phil Nash5bbdc8f2015-07-15 23:03:11 +010011156#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" )
Phil Nash90a35942012-11-13 22:04:29 +000011157#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011158
Martin Hořeňovský9a566092017-01-20 12:49:59 +010011159#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
Phil Nash90a35942012-11-13 22:04:29 +000011160#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011161
Phil Nasha2773812013-02-02 20:37:58 +000011162#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
Phil Nash859760a2013-12-14 14:34:05 +000011163#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
Phil Nashb5fd5a62013-06-28 17:09:57 +010011164#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
Phil Nasha2773812013-02-02 20:37:58 +000011165#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
Phil Nashb5fd5a62013-06-28 17:09:57 +010011166#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011167
Phil Nash93906752013-03-16 20:21:51 +000011168#ifdef CATCH_CONFIG_VARIADIC_MACROS
11169 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
Phil Nash786959d2013-06-07 19:07:50 +010011170 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000011171 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
Phil Nashc7243562016-01-22 07:52:07 +000011172 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000011173 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
Phil Nash859760a2013-12-14 14:34:05 +000011174 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
Phil Nash66d641a2013-12-14 23:16:44 +000011175 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000011176#else
11177 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
Phil Nash786959d2013-06-07 19:07:50 +010011178 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
Phil Nash93906752013-03-16 20:21:51 +000011179 #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 +000011180 #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
Phil Nash93906752013-03-16 20:21:51 +000011181 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
Phil Nash859760a2013-12-14 14:34:05 +000011182 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
Phil Nash66d641a2013-12-14 23:16:44 +000011183 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
Phil Nash93906752013-03-16 20:21:51 +000011184#endif
11185#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011186
11187#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +000011188#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011189
11190#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
11191
Phil Nash37186a12013-03-13 12:19:30 +000011192// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +000011193#ifdef CATCH_CONFIG_VARIADIC_MACROS
11194#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
Phil Nash544bf332014-08-20 08:09:32 +010011195#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
Phil Nashbd7f7972013-03-21 09:00:24 +000011196#else
Phil Nash37186a12013-03-13 12:19:30 +000011197#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
Phil Nash544bf332014-08-20 08:09:32 +010011198#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +000011199#endif
Phil Nash2f6371f2015-07-23 23:06:26 +010011200#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" )
11201#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
11202#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
11203#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
11204#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
Phil Nash37186a12013-03-13 12:19:30 +000011205
Phil Nash46bcd4b2012-07-20 18:43:48 +010011206// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
11207#else
11208
Phil Nash90a35942012-11-13 22:04:29 +000011209#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
Phil Nashab036682014-06-02 07:48:03 +010011210#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011211
Phil Nash93a842e2015-07-13 06:36:07 +010011212#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
Phil Nash90a35942012-11-13 22:04:29 +000011213#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
Phil Nash5bbdc8f2015-07-15 23:03:11 +010011214#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" )
Phil Nash90a35942012-11-13 22:04:29 +000011215#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011216
Phil Nash90a35942012-11-13 22:04:29 +000011217#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
Phil Nashab036682014-06-02 07:48:03 +010011218#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
Phil Nash90a35942012-11-13 22:04:29 +000011219#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
11220#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
11221#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011222
Phil Nash93a842e2015-07-13 06:36:07 +010011223#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
Phil Nash90a35942012-11-13 22:04:29 +000011224#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
Phil Nash5bbdc8f2015-07-15 23:03:11 +010011225#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" )
Phil Nash90a35942012-11-13 22:04:29 +000011226#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011227
Phil Nash90a35942012-11-13 22:04:29 +000011228#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
11229#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
Phil Nash78d95a02012-03-04 21:22:36 +000011230
Phil Nasha2773812013-02-02 20:37:58 +000011231#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
Phil Nash859760a2013-12-14 14:34:05 +000011232#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
Phil Nashb5fd5a62013-06-28 17:09:57 +010011233#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
Phil Nasha2773812013-02-02 20:37:58 +000011234#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
Phil Nashb5fd5a62013-06-28 17:09:57 +010011235#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011236
Phil Nash93906752013-03-16 20:21:51 +000011237#ifdef CATCH_CONFIG_VARIADIC_MACROS
11238 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
Phil Nash786959d2013-06-07 19:07:50 +010011239 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000011240 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
Phil Nashc7243562016-01-22 07:52:07 +000011241 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000011242 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
Phil Nash859760a2013-12-14 14:34:05 +000011243 #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
Phil Nash66d641a2013-12-14 23:16:44 +000011244 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000011245#else
11246 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
Phil Nash786959d2013-06-07 19:07:50 +010011247 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
Phil Nash93906752013-03-16 20:21:51 +000011248 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
Phil Nash7424b232015-12-28 15:07:32 +000011249 #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
Phil Nash93906752013-03-16 20:21:51 +000011250 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
Phil Nash859760a2013-12-14 14:34:05 +000011251 #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
Phil Nash66d641a2013-12-14 23:16:44 +000011252 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
Phil Nash93906752013-03-16 20:21:51 +000011253#endif
11254#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011255
11256#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +000011257#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011258
11259#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
11260
Phil Nash46bcd4b2012-07-20 18:43:48 +010011261#endif
11262
11263#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011264
Phil Nash37186a12013-03-13 12:19:30 +000011265// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +000011266#ifdef CATCH_CONFIG_VARIADIC_MACROS
11267#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
Phil Nash544bf332014-08-20 08:09:32 +010011268#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
Phil Nashbd7f7972013-03-21 09:00:24 +000011269#else
Phil Nash37186a12013-03-13 12:19:30 +000011270#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
Phil Nash544bf332014-08-20 08:09:32 +010011271#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +000011272#endif
Phil Nash2f6371f2015-07-23 23:06:26 +010011273#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
11274#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" )
11275#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
11276#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
11277#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
Phil Nash37186a12013-03-13 12:19:30 +000011278
Phil Nash89d1e6c2011-05-24 08:23:02 +010011279using Catch::Detail::Approx;
11280
Phil Nashaec1e5e2012-05-09 19:37:51 +010011281#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010011282