GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
* Catch v1.5.1 |
||
3 |
* Generated: 2016-04-28 08:12:37.387488 |
||
4 |
* ---------------------------------------------------------- |
||
5 |
* 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. |
||
7 |
* |
||
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) |
||
10 |
*/ |
||
11 |
#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED |
||
12 |
#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED |
||
13 |
|||
14 |
#define TWOBLUECUBES_CATCH_HPP_INCLUDED |
||
15 |
|||
16 |
#ifdef __clang__ |
||
17 |
# pragma clang system_header |
||
18 |
#elif defined __GNUC__ |
||
19 |
# pragma GCC system_header |
||
20 |
#endif |
||
21 |
|||
22 |
// #included from: internal/catch_suppress_warnings.h |
||
23 |
|||
24 |
#ifdef __clang__ |
||
25 |
# 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" |
||
37 |
# pragma clang diagnostic ignored "-Wswitch-enum" |
||
38 |
# pragma clang diagnostic ignored "-Wcovered-switch-default" |
||
39 |
# endif |
||
40 |
#elif defined __GNUC__ |
||
41 |
# pragma GCC diagnostic ignored "-Wvariadic-macros" |
||
42 |
# pragma GCC diagnostic ignored "-Wunused-variable" |
||
43 |
# pragma GCC diagnostic push |
||
44 |
# pragma GCC diagnostic ignored "-Wpadded" |
||
45 |
#endif |
||
46 |
#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) |
||
47 |
# define CATCH_IMPL |
||
48 |
#endif |
||
49 |
|||
50 |
#ifdef CATCH_IMPL |
||
51 |
# ifndef CLARA_CONFIG_MAIN |
||
52 |
# define CLARA_CONFIG_MAIN_NOT_DEFINED |
||
53 |
# define CLARA_CONFIG_MAIN |
||
54 |
# endif |
||
55 |
#endif |
||
56 |
|||
57 |
// #included from: internal/catch_notimplemented_exception.h |
||
58 |
#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED |
||
59 |
|||
60 |
// #included from: catch_common.h |
||
61 |
#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED |
||
62 |
|||
63 |
#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line |
||
64 |
#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) |
||
65 |
#ifdef CATCH_CONFIG_COUNTER |
||
66 |
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) |
||
67 |
#else |
||
68 |
# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) |
||
69 |
#endif |
||
70 |
|||
71 |
#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr |
||
72 |
#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) |
||
73 |
|||
74 |
#include <sstream> |
||
75 |
#include <stdexcept> |
||
76 |
#include <algorithm> |
||
77 |
|||
78 |
// stack |
||
79 |
#ifdef HAVE_EXECINFO |
||
80 |
#include <execinfo.h> |
||
81 |
#endif // HAVE_EXECINFO |
||
82 |
// stack |
||
83 |
|||
84 |
// #included from: catch_compiler_capabilities.h |
||
85 |
#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED |
||
86 |
|||
87 |
// Detect a number of compiler features - mostly C++11/14 conformance - by compiler |
||
88 |
// The following features are defined: |
||
89 |
// |
||
90 |
// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? |
||
91 |
// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? |
||
92 |
// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods |
||
93 |
// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? |
||
94 |
// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported |
||
95 |
// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? |
||
96 |
// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? |
||
97 |
// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) |
||
98 |
|||
99 |
// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? |
||
100 |
|||
101 |
// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? |
||
102 |
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? |
||
103 |
// **************** |
||
104 |
// Note to maintainers: if new toggles are added please document them |
||
105 |
// in configuration.md, too |
||
106 |
// **************** |
||
107 |
|||
108 |
// In general each macro has a _NO_<feature name> form |
||
109 |
// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. |
||
110 |
// Many features, at point of detection, define an _INTERNAL_ macro, so they |
||
111 |
// can be combined, en-mass, with the _NO_ forms later. |
||
112 |
|||
113 |
// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 |
||
114 |
|||
115 |
#if defined(__cplusplus) && __cplusplus >= 201103L |
||
116 |
# define CATCH_CPP11_OR_GREATER |
||
117 |
#endif |
||
118 |
|||
119 |
#ifdef __clang__ |
||
120 |
|||
121 |
# if __has_feature(cxx_nullptr) |
||
122 |
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR |
||
123 |
# endif |
||
124 |
|||
125 |
# if __has_feature(cxx_noexcept) |
||
126 |
# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT |
||
127 |
# endif |
||
128 |
|||
129 |
# if defined(CATCH_CPP11_OR_GREATER) |
||
130 |
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) |
||
131 |
# endif |
||
132 |
|||
133 |
#endif // __clang__ |
||
134 |
|||
135 |
//////////////////////////////////////////////////////////////////////////////// |
||
136 |
// Borland |
||
137 |
#ifdef __BORLANDC__ |
||
138 |
|||
139 |
#endif // __BORLANDC__ |
||
140 |
|||
141 |
//////////////////////////////////////////////////////////////////////////////// |
||
142 |
// EDG |
||
143 |
#ifdef __EDG_VERSION__ |
||
144 |
|||
145 |
#endif // __EDG_VERSION__ |
||
146 |
|||
147 |
//////////////////////////////////////////////////////////////////////////////// |
||
148 |
// Digital Mars |
||
149 |
#ifdef __DMC__ |
||
150 |
|||
151 |
#endif // __DMC__ |
||
152 |
|||
153 |
//////////////////////////////////////////////////////////////////////////////// |
||
154 |
// GCC |
||
155 |
#ifdef __GNUC__ |
||
156 |
|||
157 |
# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) |
||
158 |
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR |
||
159 |
# endif |
||
160 |
|||
161 |
# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) |
||
162 |
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) |
||
163 |
# endif |
||
164 |
|||
165 |
// - otherwise more recent versions define __cplusplus >= 201103L |
||
166 |
// and will get picked up below |
||
167 |
|||
168 |
#endif // __GNUC__ |
||
169 |
|||
170 |
//////////////////////////////////////////////////////////////////////////////// |
||
171 |
// Visual C++ |
||
172 |
#ifdef _MSC_VER |
||
173 |
|||
174 |
#if (_MSC_VER >= 1600) |
||
175 |
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR |
||
176 |
# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR |
||
177 |
#endif |
||
178 |
|||
179 |
#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) |
||
180 |
#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT |
||
181 |
#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS |
||
182 |
#endif |
||
183 |
|||
184 |
#endif // _MSC_VER |
||
185 |
|||
186 |
//////////////////////////////////////////////////////////////////////////////// |
||
187 |
|||
188 |
// Use variadic macros if the compiler supports them |
||
189 |
#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ |
||
190 |
( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ |
||
191 |
( defined __GNUC__ && __GNUC__ >= 3 ) || \ |
||
192 |
( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) |
||
193 |
|||
194 |
#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS |
||
195 |
|||
196 |
#endif |
||
197 |
|||
198 |
// Use __COUNTER__ if the compiler supports it |
||
199 |
#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ |
||
200 |
( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ |
||
201 |
( defined __clang__ && __clang_major__ >= 3 ) |
||
202 |
|||
203 |
#define CATCH_INTERNAL_CONFIG_COUNTER |
||
204 |
|||
205 |
#endif |
||
206 |
|||
207 |
//////////////////////////////////////////////////////////////////////////////// |
||
208 |
// C++ language feature support |
||
209 |
|||
210 |
// catch all support for C++11 |
||
211 |
#if defined(CATCH_CPP11_OR_GREATER) |
||
212 |
|||
213 |
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) |
||
214 |
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR |
||
215 |
# endif |
||
216 |
|||
217 |
# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT |
||
218 |
# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT |
||
219 |
# endif |
||
220 |
|||
221 |
# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS |
||
222 |
# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS |
||
223 |
# endif |
||
224 |
|||
225 |
# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM |
||
226 |
# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM |
||
227 |
# endif |
||
228 |
|||
229 |
# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE |
||
230 |
# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE |
||
231 |
# endif |
||
232 |
|||
233 |
# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS |
||
234 |
# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS |
||
235 |
# endif |
||
236 |
|||
237 |
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) |
||
238 |
# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG |
||
239 |
# endif |
||
240 |
|||
241 |
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) |
||
242 |
# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE |
||
243 |
# endif |
||
244 |
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) |
||
245 |
# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR |
||
246 |
# endif |
||
247 |
|||
248 |
#endif // __cplusplus >= 201103L |
||
249 |
|||
250 |
// Now set the actual defines based on the above + anything the user has configured |
||
251 |
#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) |
||
252 |
# define CATCH_CONFIG_CPP11_NULLPTR |
||
253 |
#endif |
||
254 |
#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) |
||
255 |
# define CATCH_CONFIG_CPP11_NOEXCEPT |
||
256 |
#endif |
||
257 |
#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) |
||
258 |
# define CATCH_CONFIG_CPP11_GENERATED_METHODS |
||
259 |
#endif |
||
260 |
#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) |
||
261 |
# define CATCH_CONFIG_CPP11_IS_ENUM |
||
262 |
#endif |
||
263 |
#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) |
||
264 |
# define CATCH_CONFIG_CPP11_TUPLE |
||
265 |
#endif |
||
266 |
#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) |
||
267 |
# define CATCH_CONFIG_VARIADIC_MACROS |
||
268 |
#endif |
||
269 |
#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) |
||
270 |
# define CATCH_CONFIG_CPP11_LONG_LONG |
||
271 |
#endif |
||
272 |
#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) |
||
273 |
# define CATCH_CONFIG_CPP11_OVERRIDE |
||
274 |
#endif |
||
275 |
#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) |
||
276 |
# define CATCH_CONFIG_CPP11_UNIQUE_PTR |
||
277 |
#endif |
||
278 |
#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) |
||
279 |
# define CATCH_CONFIG_COUNTER |
||
280 |
#endif |
||
281 |
|||
282 |
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) |
||
283 |
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS |
||
284 |
#endif |
||
285 |
|||
286 |
// noexcept support: |
||
287 |
#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) |
||
288 |
# define CATCH_NOEXCEPT noexcept |
||
289 |
# define CATCH_NOEXCEPT_IS(x) noexcept(x) |
||
290 |
#else |
||
291 |
# define CATCH_NOEXCEPT throw() |
||
292 |
# define CATCH_NOEXCEPT_IS(x) |
||
293 |
#endif |
||
294 |
|||
295 |
// nullptr support |
||
296 |
#ifdef CATCH_CONFIG_CPP11_NULLPTR |
||
297 |
# define CATCH_NULL nullptr |
||
298 |
#else |
||
299 |
# define CATCH_NULL NULL |
||
300 |
#endif |
||
301 |
|||
302 |
// override support |
||
303 |
#ifdef CATCH_CONFIG_CPP11_OVERRIDE |
||
304 |
# define CATCH_OVERRIDE override |
||
305 |
#else |
||
306 |
# define CATCH_OVERRIDE |
||
307 |
#endif |
||
308 |
|||
309 |
// unique_ptr support |
||
310 |
#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR |
||
311 |
# define CATCH_AUTO_PTR( T ) std::unique_ptr<T> |
||
312 |
#else |
||
313 |
# define CATCH_AUTO_PTR( T ) std::auto_ptr<T> |
||
314 |
#endif |
||
315 |
|||
316 |
namespace Catch { |
||
317 |
|||
318 |
struct IConfig; |
||
319 |
|||
320 |
struct CaseSensitive { enum Choice { |
||
321 |
Yes, |
||
322 |
No |
||
323 |
}; }; |
||
324 |
|||
325 |
class NonCopyable { |
||
326 |
#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS |
||
327 |
NonCopyable( NonCopyable const& ) = delete; |
||
328 |
NonCopyable( NonCopyable && ) = delete; |
||
329 |
NonCopyable& operator = ( NonCopyable const& ) = delete; |
||
330 |
NonCopyable& operator = ( NonCopyable && ) = delete; |
||
331 |
#else |
||
332 |
NonCopyable( NonCopyable const& info ); |
||
333 |
NonCopyable& operator = ( NonCopyable const& ); |
||
334 |
#endif |
||
335 |
|||
336 |
protected: |
||
337 |
9892 |
NonCopyable() {} |
|
338 |
virtual ~NonCopyable(); |
||
339 |
}; |
||
340 |
|||
341 |
class SafeBool { |
||
342 |
public: |
||
343 |
typedef void (SafeBool::*type)() const; |
||
344 |
|||
345 |
static type makeSafe( bool value ) { |
||
346 |
✗✗✓✗ ✗✗✗✓ ✓✗ |
3 |
return value ? &SafeBool::trueValue : 0; |
347 |
} |
||
348 |
private: |
||
349 |
void trueValue() const {} |
||
350 |
}; |
||
351 |
|||
352 |
template<typename ContainerT> |
||
353 |
inline void deleteAll( ContainerT& container ) { |
||
354 |
2 |
typename ContainerT::const_iterator it = container.begin(); |
|
355 |
2 |
typename ContainerT::const_iterator itEnd = container.end(); |
|
356 |
✗✗✗✓ |
1 |
for(; it != itEnd; ++it ) |
357 |
delete *it; |
||
358 |
} |
||
359 |
template<typename AssociativeContainerT> |
||
360 |
inline void deleteAllValues( AssociativeContainerT& container ) { |
||
361 |
typename AssociativeContainerT::const_iterator it = container.begin(); |
||
362 |
typename AssociativeContainerT::const_iterator itEnd = container.end(); |
||
363 |
for(; it != itEnd; ++it ) |
||
364 |
delete it->second; |
||
365 |
} |
||
366 |
|||
367 |
bool startsWith( std::string const& s, std::string const& prefix ); |
||
368 |
bool endsWith( std::string const& s, std::string const& suffix ); |
||
369 |
bool contains( std::string const& s, std::string const& infix ); |
||
370 |
void toLowerInPlace( std::string& s ); |
||
371 |
std::string toLower( std::string const& s ); |
||
372 |
std::string trim( std::string const& str ); |
||
373 |
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); |
||
374 |
|||
375 |
4 |
struct pluralise { |
|
376 |
pluralise( std::size_t count, std::string const& label ); |
||
377 |
|||
378 |
friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); |
||
379 |
|||
380 |
std::size_t m_count; |
||
381 |
std::string m_label; |
||
382 |
}; |
||
383 |
|||
384 |
✗✗✗✗ |
18695644 |
struct SourceLineInfo { |
385 |
|||
386 |
SourceLineInfo(); |
||
387 |
SourceLineInfo( char const* _file, std::size_t _line ); |
||
388 |
SourceLineInfo( SourceLineInfo const& other ); |
||
389 |
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS |
||
390 |
2 |
SourceLineInfo( SourceLineInfo && ) = default; |
|
391 |
SourceLineInfo& operator = ( SourceLineInfo const& ) = default; |
||
392 |
SourceLineInfo& operator = ( SourceLineInfo && ) = default; |
||
393 |
# endif |
||
394 |
bool empty() const; |
||
395 |
bool operator == ( SourceLineInfo const& other ) const; |
||
396 |
bool operator < ( SourceLineInfo const& other ) const; |
||
397 |
|||
398 |
std::string file; |
||
399 |
std::size_t line; |
||
400 |
}; |
||
401 |
|||
402 |
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); |
||
403 |
|||
404 |
// This is just here to avoid compiler warnings with macro constants and boolean literals |
||
405 |
inline bool isTrue( bool value ){ return value; } |
||
406 |
inline bool alwaysTrue() { return true; } |
||
407 |
inline bool alwaysFalse() { return false; } |
||
408 |
|||
409 |
void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); |
||
410 |
|||
411 |
void seedRng( IConfig const& config ); |
||
412 |
unsigned int rngSeed(); |
||
413 |
|||
414 |
// Use this in variadic streaming macros to allow |
||
415 |
// >> +StreamEndStop |
||
416 |
// as well as |
||
417 |
// >> stuff +StreamEndStop |
||
418 |
struct StreamEndStop { |
||
419 |
std::string operator+() { |
||
420 |
return std::string(); |
||
421 |
} |
||
422 |
}; |
||
423 |
template<typename T> |
||
424 |
T const& operator + ( T const& value, StreamEndStop ) { |
||
425 |
return value; |
||
426 |
} |
||
427 |
} |
||
428 |
|||
429 |
#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) |
||
430 |
#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); |
||
431 |
|||
432 |
#include <ostream> |
||
433 |
|||
434 |
namespace Catch { |
||
435 |
|||
436 |
class NotImplementedException : public std::exception |
||
437 |
{ |
||
438 |
public: |
||
439 |
NotImplementedException( SourceLineInfo const& lineInfo ); |
||
440 |
NotImplementedException( NotImplementedException const& ) {} |
||
441 |
|||
442 |
virtual ~NotImplementedException() CATCH_NOEXCEPT {} |
||
443 |
|||
444 |
virtual const char* what() const CATCH_NOEXCEPT; |
||
445 |
|||
446 |
private: |
||
447 |
std::string m_what; |
||
448 |
SourceLineInfo m_lineInfo; |
||
449 |
}; |
||
450 |
|||
451 |
} // end namespace Catch |
||
452 |
|||
453 |
/////////////////////////////////////////////////////////////////////////////// |
||
454 |
#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) |
||
455 |
|||
456 |
// #included from: internal/catch_context.h |
||
457 |
#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED |
||
458 |
|||
459 |
// #included from: catch_interfaces_generators.h |
||
460 |
#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED |
||
461 |
|||
462 |
#include <string> |
||
463 |
|||
464 |
namespace Catch { |
||
465 |
|||
466 |
struct IGeneratorInfo { |
||
467 |
virtual ~IGeneratorInfo(); |
||
468 |
virtual bool moveNext() = 0; |
||
469 |
virtual std::size_t getCurrentIndex() const = 0; |
||
470 |
}; |
||
471 |
|||
472 |
struct IGeneratorsForTest { |
||
473 |
virtual ~IGeneratorsForTest(); |
||
474 |
|||
475 |
virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; |
||
476 |
virtual bool moveNext() = 0; |
||
477 |
}; |
||
478 |
|||
479 |
IGeneratorsForTest* createGeneratorsForTest(); |
||
480 |
|||
481 |
} // end namespace Catch |
||
482 |
|||
483 |
// #included from: catch_ptr.hpp |
||
484 |
#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED |
||
485 |
|||
486 |
#ifdef __clang__ |
||
487 |
#pragma clang diagnostic push |
||
488 |
#pragma clang diagnostic ignored "-Wpadded" |
||
489 |
#endif |
||
490 |
|||
491 |
namespace Catch { |
||
492 |
|||
493 |
// An intrusive reference counting smart pointer. |
||
494 |
// T must implement addRef() and release() methods |
||
495 |
// typically implementing the IShared interface |
||
496 |
template<typename T> |
||
497 |
class Ptr { |
||
498 |
public: |
||
499 |
4 |
Ptr() : m_p( CATCH_NULL ){} |
|
500 |
1593 |
Ptr( T* p ) : m_p( p ){ |
|
501 |
✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✗✗✓✗ ✓✗✓✗ ✓✗ |
1592 |
if( m_p ) |
502 |
✓✗✓✗ ✗✗✓✗ ✗✗ |
1592 |
m_p->addRef(); |
503 |
} |
||
504 |
167128 |
Ptr( Ptr const& other ) : m_p( other.m_p ){ |
|
505 |
✗✗✓✗ ✗✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✓✗✓✗ ✓✗ |
167128 |
if( m_p ) |
506 |
✗✗✓✗ ✗✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✗✗ ✓✗✓✗ ✓✗✗✗ ✓✗✓✗ ✓✗ |
167128 |
m_p->addRef(); |
507 |
} |
||
508 |
~Ptr(){ |
||
509 |
✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✓✗✗✗ ✓✗✗✗ ✓✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✓✓✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗✗✓✗ ✓✗✗✗ ✓✗✗✓ ✓✗✗✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✓✓✓✗ ✗✗ |
168725 |
if( m_p ) |
510 |
168720 |
m_p->release(); |
|
511 |
3834 |
} |
|
512 |
void reset() { |
||
513 |
✗✗✗✓ |
1 |
if( m_p ) |
514 |
m_p->release(); |
||
515 |
1 |
m_p = CATCH_NULL; |
|
516 |
} |
||
517 |
Ptr& operator = ( T* p ){ |
||
518 |
790 |
Ptr temp( p ); |
|
519 |
396 |
swap( temp ); |
|
520 |
396 |
return *this; |
|
521 |
} |
||
522 |
4 |
Ptr& operator = ( Ptr const& other ){ |
|
523 |
8 |
Ptr temp( other ); |
|
524 |
4 |
swap( temp ); |
|
525 |
8 |
return *this; |
|
526 |
} |
||
527 |
800 |
void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } |
|
528 |
8968 |
T* get() const{ return m_p; } |
|
529 |
1537 |
T& operator*() const { return *m_p; } |
|
530 |
3230883 |
T* operator->() const { return m_p; } |
|
531 |
3 |
bool operator !() const { return m_p == CATCH_NULL; } |
|
532 |
4 |
operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } |
|
533 |
|||
534 |
private: |
||
535 |
T* m_p; |
||
536 |
}; |
||
537 |
|||
538 |
3242 |
struct IShared : NonCopyable { |
|
539 |
virtual ~IShared(); |
||
540 |
virtual void addRef() const = 0; |
||
541 |
virtual void release() const = 0; |
||
542 |
}; |
||
543 |
|||
544 |
template<typename T = IShared> |
||
545 |
3242 |
struct SharedImpl : T { |
|
546 |
|||
547 |
3242 |
SharedImpl() : m_rc( 0 ){} |
|
548 |
|||
549 |
168720 |
virtual void addRef() const { |
|
550 |
168720 |
++m_rc; |
|
551 |
168720 |
} |
|
552 |
168720 |
virtual void release() const { |
|
553 |
✓✓✓✓ ✓✓✓✓ ✓✓ |
168720 |
if( --m_rc == 0 ) |
554 |
1590 |
delete this; |
|
555 |
168720 |
} |
|
556 |
|||
557 |
mutable unsigned int m_rc; |
||
558 |
}; |
||
559 |
|||
560 |
} // end namespace Catch |
||
561 |
|||
562 |
#ifdef __clang__ |
||
563 |
#pragma clang diagnostic pop |
||
564 |
#endif |
||
565 |
|||
566 |
#include <memory> |
||
567 |
#include <vector> |
||
568 |
#include <stdlib.h> |
||
569 |
|||
570 |
namespace Catch { |
||
571 |
|||
572 |
class TestCase; |
||
573 |
class Stream; |
||
574 |
struct IResultCapture; |
||
575 |
struct IRunner; |
||
576 |
struct IGeneratorsForTest; |
||
577 |
struct IConfig; |
||
578 |
|||
579 |
struct IContext |
||
580 |
{ |
||
581 |
virtual ~IContext(); |
||
582 |
|||
583 |
virtual IResultCapture* getResultCapture() = 0; |
||
584 |
virtual IRunner* getRunner() = 0; |
||
585 |
virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; |
||
586 |
virtual bool advanceGeneratorsForCurrentTest() = 0; |
||
587 |
virtual Ptr<IConfig const> getConfig() const = 0; |
||
588 |
}; |
||
589 |
|||
590 |
1 |
struct IMutableContext : IContext |
|
591 |
{ |
||
592 |
virtual ~IMutableContext(); |
||
593 |
virtual void setResultCapture( IResultCapture* resultCapture ) = 0; |
||
594 |
virtual void setRunner( IRunner* runner ) = 0; |
||
595 |
virtual void setConfig( Ptr<IConfig const> const& config ) = 0; |
||
596 |
}; |
||
597 |
|||
598 |
IContext& getCurrentContext(); |
||
599 |
IMutableContext& getCurrentMutableContext(); |
||
600 |
void cleanUpContext(); |
||
601 |
Stream createStream( std::string const& streamName ); |
||
602 |
|||
603 |
} |
||
604 |
|||
605 |
// #included from: internal/catch_test_registry.hpp |
||
606 |
#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED |
||
607 |
|||
608 |
// #included from: catch_interfaces_testcase.h |
||
609 |
#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED |
||
610 |
|||
611 |
#include <vector> |
||
612 |
|||
613 |
namespace Catch { |
||
614 |
|||
615 |
class TestSpec; |
||
616 |
|||
617 |
788 |
struct ITestCase : IShared { |
|
618 |
virtual void invoke () const = 0; |
||
619 |
protected: |
||
620 |
virtual ~ITestCase(); |
||
621 |
}; |
||
622 |
|||
623 |
class TestCase; |
||
624 |
struct IConfig; |
||
625 |
|||
626 |
struct ITestCaseRegistry { |
||
627 |
virtual ~ITestCaseRegistry(); |
||
628 |
virtual std::vector<TestCase> const& getAllTests() const = 0; |
||
629 |
virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0; |
||
630 |
}; |
||
631 |
|||
632 |
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); |
||
633 |
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); |
||
634 |
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); |
||
635 |
|||
636 |
} |
||
637 |
|||
638 |
namespace Catch { |
||
639 |
|||
640 |
template<typename C> |
||
641 |
class MethodTestCase : public SharedImpl<ITestCase> { |
||
642 |
|||
643 |
public: |
||
644 |
MethodTestCase( void (C::*method)() ) : m_method( method ) {} |
||
645 |
|||
646 |
virtual void invoke() const { |
||
647 |
C obj; |
||
648 |
(obj.*m_method)(); |
||
649 |
} |
||
650 |
|||
651 |
private: |
||
652 |
virtual ~MethodTestCase() {} |
||
653 |
|||
654 |
void (C::*m_method)(); |
||
655 |
}; |
||
656 |
|||
657 |
typedef void(*TestFunction)(); |
||
658 |
|||
659 |
struct NameAndDesc { |
||
660 |
NameAndDesc( const char* _name = "", const char* _description= "" ) |
||
661 |
394 |
: name( _name ), description( _description ) |
|
662 |
{} |
||
663 |
|||
664 |
const char* name; |
||
665 |
const char* description; |
||
666 |
}; |
||
667 |
|||
668 |
void registerTestCase |
||
669 |
( ITestCase* testCase, |
||
670 |
char const* className, |
||
671 |
NameAndDesc const& nameAndDesc, |
||
672 |
SourceLineInfo const& lineInfo ); |
||
673 |
|||
674 |
struct AutoReg { |
||
675 |
|||
676 |
AutoReg |
||
677 |
( TestFunction function, |
||
678 |
SourceLineInfo const& lineInfo, |
||
679 |
NameAndDesc const& nameAndDesc ); |
||
680 |
|||
681 |
template<typename C> |
||
682 |
AutoReg |
||
683 |
( void (C::*method)(), |
||
684 |
char const* className, |
||
685 |
NameAndDesc const& nameAndDesc, |
||
686 |
SourceLineInfo const& lineInfo ) { |
||
687 |
|||
688 |
registerTestCase |
||
689 |
( new MethodTestCase<C>( method ), |
||
690 |
className, |
||
691 |
nameAndDesc, |
||
692 |
lineInfo ); |
||
693 |
} |
||
694 |
|||
695 |
~AutoReg(); |
||
696 |
|||
697 |
private: |
||
698 |
AutoReg( AutoReg const& ); |
||
699 |
void operator= ( AutoReg const& ); |
||
700 |
}; |
||
701 |
|||
702 |
void registerTestCaseFunction |
||
703 |
( TestFunction function, |
||
704 |
SourceLineInfo const& lineInfo, |
||
705 |
NameAndDesc const& nameAndDesc ); |
||
706 |
|||
707 |
} // end namespace Catch |
||
708 |
|||
709 |
#ifdef CATCH_CONFIG_VARIADIC_MACROS |
||
710 |
/////////////////////////////////////////////////////////////////////////////// |
||
711 |
#define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ |
||
712 |
static void TestName(); \ |
||
713 |
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ |
||
714 |
static void TestName() |
||
715 |
#define INTERNAL_CATCH_TESTCASE( ... ) \ |
||
716 |
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) |
||
717 |
|||
718 |
/////////////////////////////////////////////////////////////////////////////// |
||
719 |
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ |
||
720 |
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } |
||
721 |
|||
722 |
/////////////////////////////////////////////////////////////////////////////// |
||
723 |
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ |
||
724 |
namespace{ \ |
||
725 |
struct TestName : ClassName{ \ |
||
726 |
void test(); \ |
||
727 |
}; \ |
||
728 |
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ |
||
729 |
} \ |
||
730 |
void TestName::test() |
||
731 |
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ |
||
732 |
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) |
||
733 |
|||
734 |
/////////////////////////////////////////////////////////////////////////////// |
||
735 |
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ |
||
736 |
Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); |
||
737 |
|||
738 |
#else |
||
739 |
/////////////////////////////////////////////////////////////////////////////// |
||
740 |
#define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ |
||
741 |
static void TestName(); \ |
||
742 |
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ |
||
743 |
static void TestName() |
||
744 |
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ |
||
745 |
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) |
||
746 |
|||
747 |
/////////////////////////////////////////////////////////////////////////////// |
||
748 |
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ |
||
749 |
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } |
||
750 |
|||
751 |
/////////////////////////////////////////////////////////////////////////////// |
||
752 |
#define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ |
||
753 |
namespace{ \ |
||
754 |
struct TestCaseName : ClassName{ \ |
||
755 |
void test(); \ |
||
756 |
}; \ |
||
757 |
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ |
||
758 |
} \ |
||
759 |
void TestCaseName::test() |
||
760 |
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ |
||
761 |
INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) |
||
762 |
|||
763 |
/////////////////////////////////////////////////////////////////////////////// |
||
764 |
#define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ |
||
765 |
Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); |
||
766 |
#endif |
||
767 |
|||
768 |
// #included from: internal/catch_capture.hpp |
||
769 |
#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED |
||
770 |
|||
771 |
// #included from: catch_result_builder.h |
||
772 |
#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED |
||
773 |
|||
774 |
// #included from: catch_result_type.h |
||
775 |
#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED |
||
776 |
|||
777 |
namespace Catch { |
||
778 |
|||
779 |
// ResultWas::OfType enum |
||
780 |
struct ResultWas { enum OfType { |
||
781 |
Unknown = -1, |
||
782 |
Ok = 0, |
||
783 |
Info = 1, |
||
784 |
Warning = 2, |
||
785 |
|||
786 |
FailureBit = 0x10, |
||
787 |
|||
788 |
ExpressionFailed = FailureBit | 1, |
||
789 |
ExplicitFailure = FailureBit | 2, |
||
790 |
|||
791 |
Exception = 0x100 | FailureBit, |
||
792 |
|||
793 |
ThrewException = Exception | 1, |
||
794 |
DidntThrowException = Exception | 2, |
||
795 |
|||
796 |
FatalErrorCondition = 0x200 | FailureBit |
||
797 |
|||
798 |
}; }; |
||
799 |
|||
800 |
inline bool isOk( ResultWas::OfType resultType ) { |
||
801 |
2865846 |
return ( resultType & ResultWas::FailureBit ) == 0; |
|
802 |
} |
||
803 |
inline bool isJustInfo( int flags ) { |
||
804 |
return flags == ResultWas::Info; |
||
805 |
} |
||
806 |
|||
807 |
// ResultDisposition::Flags enum |
||
808 |
struct ResultDisposition { enum Flags { |
||
809 |
Normal = 0x01, |
||
810 |
|||
811 |
ContinueOnFailure = 0x02, // Failures fail test, but execution continues |
||
812 |
FalseTest = 0x04, // Prefix expression with ! |
||
813 |
SuppressFail = 0x08 // Failures are reported but do not fail the test |
||
814 |
}; }; |
||
815 |
|||
816 |
inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { |
||
817 |
return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) ); |
||
818 |
} |
||
819 |
|||
820 |
inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } |
||
821 |
1432892 |
inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } |
|
822 |
inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } |
||
823 |
|||
824 |
} // end namespace Catch |
||
825 |
|||
826 |
// #included from: catch_assertionresult.h |
||
827 |
#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED |
||
828 |
|||
829 |
#include <string> |
||
830 |
|||
831 |
namespace Catch { |
||
832 |
|||
833 |
42992168 |
struct AssertionInfo |
|
834 |
{ |
||
835 |
8 |
AssertionInfo() {} |
|
836 |
AssertionInfo( std::string const& _macroName, |
||
837 |
SourceLineInfo const& _lineInfo, |
||
838 |
std::string const& _capturedExpression, |
||
839 |
ResultDisposition::Flags _resultDisposition ); |
||
840 |
|||
841 |
std::string macroName; |
||
842 |
SourceLineInfo lineInfo; |
||
843 |
std::string capturedExpression; |
||
844 |
ResultDisposition::Flags resultDisposition; |
||
845 |
}; |
||
846 |
|||
847 |
34390155 |
struct AssertionResultData |
|
848 |
{ |
||
849 |
4298772 |
AssertionResultData() : resultType( ResultWas::Unknown ) {} |
|
850 |
|||
851 |
std::string reconstructedExpression; |
||
852 |
std::string message; |
||
853 |
ResultWas::OfType resultType; |
||
854 |
}; |
||
855 |
|||
856 |
2865846 |
class AssertionResult { |
|
857 |
public: |
||
858 |
AssertionResult(); |
||
859 |
AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); |
||
860 |
~AssertionResult(); |
||
861 |
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS |
||
862 |
✓✗ | 1432923 |
AssertionResult( AssertionResult const& ) = default; |
863 |
AssertionResult( AssertionResult && ) = default; |
||
864 |
AssertionResult& operator = ( AssertionResult const& ) = default; |
||
865 |
AssertionResult& operator = ( AssertionResult && ) = default; |
||
866 |
# endif |
||
867 |
|||
868 |
bool isOk() const; |
||
869 |
bool succeeded() const; |
||
870 |
ResultWas::OfType getResultType() const; |
||
871 |
bool hasExpression() const; |
||
872 |
bool hasMessage() const; |
||
873 |
std::string getExpression() const; |
||
874 |
std::string getExpressionInMacro() const; |
||
875 |
bool hasExpandedExpression() const; |
||
876 |
std::string getExpandedExpression() const; |
||
877 |
std::string getMessage() const; |
||
878 |
SourceLineInfo getSourceInfo() const; |
||
879 |
std::string getTestMacroName() const; |
||
880 |
|||
881 |
protected: |
||
882 |
AssertionInfo m_info; |
||
883 |
AssertionResultData m_resultData; |
||
884 |
}; |
||
885 |
|||
886 |
} // end namespace Catch |
||
887 |
|||
888 |
// #included from: catch_matchers.hpp |
||
889 |
#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED |
||
890 |
|||
891 |
namespace Catch { |
||
892 |
namespace Matchers { |
||
893 |
namespace Impl { |
||
894 |
|||
895 |
namespace Generic { |
||
896 |
template<typename ExpressionT> class AllOf; |
||
897 |
template<typename ExpressionT> class AnyOf; |
||
898 |
template<typename ExpressionT> class Not; |
||
899 |
} |
||
900 |
|||
901 |
template<typename ExpressionT> |
||
902 |
62 |
struct Matcher : SharedImpl<IShared> |
|
903 |
{ |
||
904 |
typedef ExpressionT ExpressionType; |
||
905 |
|||
906 |
62 |
virtual ~Matcher() {} |
|
907 |
virtual Ptr<Matcher> clone() const = 0; |
||
908 |
virtual bool match( ExpressionT const& expr ) const = 0; |
||
909 |
virtual std::string toString() const = 0; |
||
910 |
|||
911 |
Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const; |
||
912 |
Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const; |
||
913 |
Generic::Not<ExpressionT> operator ! () const; |
||
914 |
}; |
||
915 |
|||
916 |
template<typename DerivedT, typename ExpressionT> |
||
917 |
124 |
struct MatcherImpl : Matcher<ExpressionT> { |
|
918 |
|||
919 |
virtual Ptr<Matcher<ExpressionT> > clone() const { |
||
920 |
return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) ); |
||
921 |
} |
||
922 |
}; |
||
923 |
|||
924 |
namespace Generic { |
||
925 |
template<typename ExpressionT> |
||
926 |
class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> { |
||
927 |
public: |
||
928 |
explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {} |
||
929 |
Not( Not const& other ) : m_matcher( other.m_matcher ) {} |
||
930 |
|||
931 |
virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { |
||
932 |
return !m_matcher->match( expr ); |
||
933 |
} |
||
934 |
|||
935 |
virtual std::string toString() const CATCH_OVERRIDE { |
||
936 |
return "not " + m_matcher->toString(); |
||
937 |
} |
||
938 |
private: |
||
939 |
Ptr< Matcher<ExpressionT> > m_matcher; |
||
940 |
}; |
||
941 |
|||
942 |
template<typename ExpressionT> |
||
943 |
62 |
class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> { |
|
944 |
public: |
||
945 |
|||
946 |
93 |
AllOf() {} |
|
947 |
AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} |
||
948 |
|||
949 |
AllOf& add( Matcher<ExpressionT> const& matcher ) { |
||
950 |
m_matchers.push_back( matcher.clone() ); |
||
951 |
return *this; |
||
952 |
} |
||
953 |
31 |
virtual bool match( ExpressionT const& expr ) const |
|
954 |
{ |
||
955 |
✗✓ | 62 |
for( std::size_t i = 0; i < m_matchers.size(); ++i ) |
956 |
if( !m_matchers[i]->match( expr ) ) |
||
957 |
return false; |
||
958 |
return true; |
||
959 |
} |
||
960 |
virtual std::string toString() const { |
||
961 |
std::ostringstream oss; |
||
962 |
oss << "( "; |
||
963 |
for( std::size_t i = 0; i < m_matchers.size(); ++i ) { |
||
964 |
if( i != 0 ) |
||
965 |
oss << " and "; |
||
966 |
oss << m_matchers[i]->toString(); |
||
967 |
} |
||
968 |
oss << " )"; |
||
969 |
return oss.str(); |
||
970 |
} |
||
971 |
|||
972 |
AllOf operator && ( Matcher<ExpressionT> const& other ) const { |
||
973 |
AllOf allOfExpr( *this ); |
||
974 |
allOfExpr.add( other ); |
||
975 |
return allOfExpr; |
||
976 |
} |
||
977 |
|||
978 |
private: |
||
979 |
std::vector<Ptr<Matcher<ExpressionT> > > m_matchers; |
||
980 |
}; |
||
981 |
|||
982 |
template<typename ExpressionT> |
||
983 |
class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> { |
||
984 |
public: |
||
985 |
|||
986 |
AnyOf() {} |
||
987 |
AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} |
||
988 |
|||
989 |
AnyOf& add( Matcher<ExpressionT> const& matcher ) { |
||
990 |
m_matchers.push_back( matcher.clone() ); |
||
991 |
return *this; |
||
992 |
} |
||
993 |
virtual bool match( ExpressionT const& expr ) const |
||
994 |
{ |
||
995 |
for( std::size_t i = 0; i < m_matchers.size(); ++i ) |
||
996 |
if( m_matchers[i]->match( expr ) ) |
||
997 |
return true; |
||
998 |
return false; |
||
999 |
} |
||
1000 |
virtual std::string toString() const { |
||
1001 |
std::ostringstream oss; |
||
1002 |
oss << "( "; |
||
1003 |
for( std::size_t i = 0; i < m_matchers.size(); ++i ) { |
||
1004 |
if( i != 0 ) |
||
1005 |
oss << " or "; |
||
1006 |
oss << m_matchers[i]->toString(); |
||
1007 |
} |
||
1008 |
oss << " )"; |
||
1009 |
return oss.str(); |
||
1010 |
} |
||
1011 |
|||
1012 |
AnyOf operator || ( Matcher<ExpressionT> const& other ) const { |
||
1013 |
AnyOf anyOfExpr( *this ); |
||
1014 |
anyOfExpr.add( other ); |
||
1015 |
return anyOfExpr; |
||
1016 |
} |
||
1017 |
|||
1018 |
private: |
||
1019 |
std::vector<Ptr<Matcher<ExpressionT> > > m_matchers; |
||
1020 |
}; |
||
1021 |
|||
1022 |
} // namespace Generic |
||
1023 |
|||
1024 |
template<typename ExpressionT> |
||
1025 |
Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const { |
||
1026 |
Generic::AllOf<ExpressionT> allOfExpr; |
||
1027 |
allOfExpr.add( *this ); |
||
1028 |
allOfExpr.add( other ); |
||
1029 |
return allOfExpr; |
||
1030 |
} |
||
1031 |
|||
1032 |
template<typename ExpressionT> |
||
1033 |
Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const { |
||
1034 |
Generic::AnyOf<ExpressionT> anyOfExpr; |
||
1035 |
anyOfExpr.add( *this ); |
||
1036 |
anyOfExpr.add( other ); |
||
1037 |
return anyOfExpr; |
||
1038 |
} |
||
1039 |
|||
1040 |
template<typename ExpressionT> |
||
1041 |
Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const { |
||
1042 |
return Generic::Not<ExpressionT>( *this ); |
||
1043 |
} |
||
1044 |
|||
1045 |
namespace StdString { |
||
1046 |
|||
1047 |
inline std::string makeString( std::string const& str ) { return str; } |
||
1048 |
inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } |
||
1049 |
|||
1050 |
struct CasedString |
||
1051 |
{ |
||
1052 |
CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) |
||
1053 |
: m_caseSensitivity( caseSensitivity ), |
||
1054 |
m_str( adjustString( str ) ) |
||
1055 |
{} |
||
1056 |
std::string adjustString( std::string const& str ) const { |
||
1057 |
return m_caseSensitivity == CaseSensitive::No |
||
1058 |
? toLower( str ) |
||
1059 |
: str; |
||
1060 |
|||
1061 |
} |
||
1062 |
std::string toStringSuffix() const |
||
1063 |
{ |
||
1064 |
return m_caseSensitivity == CaseSensitive::No |
||
1065 |
? " (case insensitive)" |
||
1066 |
: ""; |
||
1067 |
} |
||
1068 |
CaseSensitive::Choice m_caseSensitivity; |
||
1069 |
std::string m_str; |
||
1070 |
}; |
||
1071 |
|||
1072 |
struct Equals : MatcherImpl<Equals, std::string> { |
||
1073 |
Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) |
||
1074 |
: m_data( str, caseSensitivity ) |
||
1075 |
{} |
||
1076 |
Equals( Equals const& other ) : m_data( other.m_data ){} |
||
1077 |
|||
1078 |
virtual ~Equals(); |
||
1079 |
|||
1080 |
virtual bool match( std::string const& expr ) const { |
||
1081 |
return m_data.m_str == m_data.adjustString( expr );; |
||
1082 |
} |
||
1083 |
virtual std::string toString() const { |
||
1084 |
return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); |
||
1085 |
} |
||
1086 |
|||
1087 |
CasedString m_data; |
||
1088 |
}; |
||
1089 |
|||
1090 |
struct Contains : MatcherImpl<Contains, std::string> { |
||
1091 |
Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) |
||
1092 |
: m_data( substr, caseSensitivity ){} |
||
1093 |
Contains( Contains const& other ) : m_data( other.m_data ){} |
||
1094 |
|||
1095 |
virtual ~Contains(); |
||
1096 |
|||
1097 |
virtual bool match( std::string const& expr ) const { |
||
1098 |
return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; |
||
1099 |
} |
||
1100 |
virtual std::string toString() const { |
||
1101 |
return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); |
||
1102 |
} |
||
1103 |
|||
1104 |
CasedString m_data; |
||
1105 |
}; |
||
1106 |
|||
1107 |
struct StartsWith : MatcherImpl<StartsWith, std::string> { |
||
1108 |
StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) |
||
1109 |
: m_data( substr, caseSensitivity ){} |
||
1110 |
|||
1111 |
StartsWith( StartsWith const& other ) : m_data( other.m_data ){} |
||
1112 |
|||
1113 |
virtual ~StartsWith(); |
||
1114 |
|||
1115 |
virtual bool match( std::string const& expr ) const { |
||
1116 |
return startsWith( m_data.adjustString( expr ), m_data.m_str ); |
||
1117 |
} |
||
1118 |
virtual std::string toString() const { |
||
1119 |
return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); |
||
1120 |
} |
||
1121 |
|||
1122 |
CasedString m_data; |
||
1123 |
}; |
||
1124 |
|||
1125 |
struct EndsWith : MatcherImpl<EndsWith, std::string> { |
||
1126 |
EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) |
||
1127 |
: m_data( substr, caseSensitivity ){} |
||
1128 |
EndsWith( EndsWith const& other ) : m_data( other.m_data ){} |
||
1129 |
|||
1130 |
virtual ~EndsWith(); |
||
1131 |
|||
1132 |
virtual bool match( std::string const& expr ) const { |
||
1133 |
return endsWith( m_data.adjustString( expr ), m_data.m_str ); |
||
1134 |
} |
||
1135 |
virtual std::string toString() const { |
||
1136 |
return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); |
||
1137 |
} |
||
1138 |
|||
1139 |
CasedString m_data; |
||
1140 |
}; |
||
1141 |
} // namespace StdString |
||
1142 |
} // namespace Impl |
||
1143 |
|||
1144 |
// The following functions create the actual matcher objects. |
||
1145 |
// This allows the types to be inferred |
||
1146 |
template<typename ExpressionT> |
||
1147 |
inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) { |
||
1148 |
return Impl::Generic::Not<ExpressionT>( m ); |
||
1149 |
} |
||
1150 |
|||
1151 |
template<typename ExpressionT> |
||
1152 |
inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1, |
||
1153 |
Impl::Matcher<ExpressionT> const& m2 ) { |
||
1154 |
return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ); |
||
1155 |
} |
||
1156 |
template<typename ExpressionT> |
||
1157 |
inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1, |
||
1158 |
Impl::Matcher<ExpressionT> const& m2, |
||
1159 |
Impl::Matcher<ExpressionT> const& m3 ) { |
||
1160 |
return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 ); |
||
1161 |
} |
||
1162 |
template<typename ExpressionT> |
||
1163 |
inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1, |
||
1164 |
Impl::Matcher<ExpressionT> const& m2 ) { |
||
1165 |
return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ); |
||
1166 |
} |
||
1167 |
template<typename ExpressionT> |
||
1168 |
inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1, |
||
1169 |
Impl::Matcher<ExpressionT> const& m2, |
||
1170 |
Impl::Matcher<ExpressionT> const& m3 ) { |
||
1171 |
return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 ); |
||
1172 |
} |
||
1173 |
|||
1174 |
inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { |
||
1175 |
return Impl::StdString::Equals( str, caseSensitivity ); |
||
1176 |
} |
||
1177 |
inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { |
||
1178 |
return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); |
||
1179 |
} |
||
1180 |
inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { |
||
1181 |
return Impl::StdString::Contains( substr, caseSensitivity ); |
||
1182 |
} |
||
1183 |
inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { |
||
1184 |
return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); |
||
1185 |
} |
||
1186 |
inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { |
||
1187 |
return Impl::StdString::StartsWith( substr ); |
||
1188 |
} |
||
1189 |
inline Impl::StdString::StartsWith StartsWith( const char* substr ) { |
||
1190 |
return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); |
||
1191 |
} |
||
1192 |
inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { |
||
1193 |
return Impl::StdString::EndsWith( substr ); |
||
1194 |
} |
||
1195 |
inline Impl::StdString::EndsWith EndsWith( const char* substr ) { |
||
1196 |
return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); |
||
1197 |
} |
||
1198 |
|||
1199 |
} // namespace Matchers |
||
1200 |
|||
1201 |
using namespace Matchers; |
||
1202 |
|||
1203 |
} // namespace Catch |
||
1204 |
|||
1205 |
namespace Catch { |
||
1206 |
|||
1207 |
struct TestFailureException{}; |
||
1208 |
|||
1209 |
template<typename T> class ExpressionLhs; |
||
1210 |
|||
1211 |
struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; |
||
1212 |
|||
1213 |
1432923 |
struct CopyableStream { |
|
1214 |
✓✗ | 1432923 |
CopyableStream() {} |
1215 |
CopyableStream( CopyableStream const& other ) { |
||
1216 |
oss << other.oss.str(); |
||
1217 |
} |
||
1218 |
CopyableStream& operator=( CopyableStream const& other ) { |
||
1219 |
oss.str(""); |
||
1220 |
oss << other.oss.str(); |
||
1221 |
return *this; |
||
1222 |
} |
||
1223 |
std::ostringstream oss; |
||
1224 |
}; |
||
1225 |
|||
1226 |
2865846 |
class ResultBuilder { |
|
1227 |
public: |
||
1228 |
ResultBuilder( char const* macroName, |
||
1229 |
SourceLineInfo const& lineInfo, |
||
1230 |
char const* capturedExpression, |
||
1231 |
ResultDisposition::Flags resultDisposition, |
||
1232 |
char const* secondArg = "" ); |
||
1233 |
|||
1234 |
template<typename T> |
||
1235 |
ExpressionLhs<T const&> operator <= ( T const& operand ); |
||
1236 |
ExpressionLhs<bool> operator <= ( bool value ); |
||
1237 |
|||
1238 |
template<typename T> |
||
1239 |
ResultBuilder& operator << ( T const& value ) { |
||
1240 |
m_stream.oss << value; |
||
1241 |
return *this; |
||
1242 |
} |
||
1243 |
|||
1244 |
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); |
||
1245 |
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); |
||
1246 |
|||
1247 |
ResultBuilder& setResultType( ResultWas::OfType result ); |
||
1248 |
ResultBuilder& setResultType( bool result ); |
||
1249 |
ResultBuilder& setLhs( std::string const& lhs ); |
||
1250 |
ResultBuilder& setRhs( std::string const& rhs ); |
||
1251 |
ResultBuilder& setOp( std::string const& op ); |
||
1252 |
|||
1253 |
void endExpression(); |
||
1254 |
|||
1255 |
std::string reconstructExpression() const; |
||
1256 |
AssertionResult build() const; |
||
1257 |
|||
1258 |
void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); |
||
1259 |
void captureResult( ResultWas::OfType resultType ); |
||
1260 |
void captureExpression(); |
||
1261 |
void captureExpectedException( std::string const& expectedMessage ); |
||
1262 |
void captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ); |
||
1263 |
void handleResult( AssertionResult const& result ); |
||
1264 |
void react(); |
||
1265 |
bool shouldDebugBreak() const; |
||
1266 |
bool allowThrows() const; |
||
1267 |
|||
1268 |
private: |
||
1269 |
AssertionInfo m_assertionInfo; |
||
1270 |
AssertionResultData m_data; |
||
1271 |
5731692 |
struct ExprComponents { |
|
1272 |
5731692 |
ExprComponents() : testFalse( false ) {} |
|
1273 |
bool testFalse; |
||
1274 |
std::string lhs, rhs, op; |
||
1275 |
} m_exprComponents; |
||
1276 |
CopyableStream m_stream; |
||
1277 |
|||
1278 |
bool m_shouldDebugBreak; |
||
1279 |
bool m_shouldThrow; |
||
1280 |
}; |
||
1281 |
|||
1282 |
} // namespace Catch |
||
1283 |
|||
1284 |
// Include after due to circular dependency: |
||
1285 |
// #included from: catch_expression_lhs.hpp |
||
1286 |
#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED |
||
1287 |
|||
1288 |
// #included from: catch_evaluate.hpp |
||
1289 |
#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED |
||
1290 |
|||
1291 |
#ifdef _MSC_VER |
||
1292 |
#pragma warning(push) |
||
1293 |
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch |
||
1294 |
#endif |
||
1295 |
|||
1296 |
#include <cstddef> |
||
1297 |
|||
1298 |
namespace Catch { |
||
1299 |
namespace Internal { |
||
1300 |
|||
1301 |
enum Operator { |
||
1302 |
IsEqualTo, |
||
1303 |
IsNotEqualTo, |
||
1304 |
IsLessThan, |
||
1305 |
IsGreaterThan, |
||
1306 |
IsLessThanOrEqualTo, |
||
1307 |
IsGreaterThanOrEqualTo |
||
1308 |
}; |
||
1309 |
|||
1310 |
template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } }; |
||
1311 |
template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } }; |
||
1312 |
template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } }; |
||
1313 |
template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } }; |
||
1314 |
template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } }; |
||
1315 |
template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } }; |
||
1316 |
template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } }; |
||
1317 |
|||
1318 |
template<typename T> |
||
1319 |
inline T& opCast(T const& t) { return const_cast<T&>(t); } |
||
1320 |
|||
1321 |
// nullptr_t support based on pull request #154 from Konstantin Baumann |
||
1322 |
#ifdef CATCH_CONFIG_CPP11_NULLPTR |
||
1323 |
inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } |
||
1324 |
#endif // CATCH_CONFIG_CPP11_NULLPTR |
||
1325 |
|||
1326 |
// So the compare overloads can be operator agnostic we convey the operator as a template |
||
1327 |
// enum, which is used to specialise an Evaluator for doing the comparison. |
||
1328 |
template<typename T1, typename T2, Operator Op> |
||
1329 |
class Evaluator{}; |
||
1330 |
|||
1331 |
template<typename T1, typename T2> |
||
1332 |
struct Evaluator<T1, T2, IsEqualTo> { |
||
1333 |
static bool evaluate( T1 const& lhs, T2 const& rhs) { |
||
1334 |
1415803 |
return bool( opCast( lhs ) == opCast( rhs ) ); |
|
1335 |
} |
||
1336 |
}; |
||
1337 |
template<typename T1, typename T2> |
||
1338 |
struct Evaluator<T1, T2, IsNotEqualTo> { |
||
1339 |
static bool evaluate( T1 const& lhs, T2 const& rhs ) { |
||
1340 |
10356 |
return bool( opCast( lhs ) != opCast( rhs ) ); |
|
1341 |
} |
||
1342 |
}; |
||
1343 |
template<typename T1, typename T2> |
||
1344 |
struct Evaluator<T1, T2, IsLessThan> { |
||
1345 |
static bool evaluate( T1 const& lhs, T2 const& rhs ) { |
||
1346 |
✓✗ | 4031 |
return bool( opCast( lhs ) < opCast( rhs ) ); |
1347 |
} |
||
1348 |
}; |
||
1349 |
template<typename T1, typename T2> |
||
1350 |
struct Evaluator<T1, T2, IsGreaterThan> { |
||
1351 |
static bool evaluate( T1 const& lhs, T2 const& rhs ) { |
||
1352 |
2685 |
return bool( opCast( lhs ) > opCast( rhs ) ); |
|
1353 |
} |
||
1354 |
}; |
||
1355 |
template<typename T1, typename T2> |
||
1356 |
struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> { |
||
1357 |
static bool evaluate( T1 const& lhs, T2 const& rhs ) { |
||
1358 |
22 |
return bool( opCast( lhs ) >= opCast( rhs ) ); |
|
1359 |
} |
||
1360 |
}; |
||
1361 |
template<typename T1, typename T2> |
||
1362 |
struct Evaluator<T1, T2, IsLessThanOrEqualTo> { |
||
1363 |
static bool evaluate( T1 const& lhs, T2 const& rhs ) { |
||
1364 |
4 |
return bool( opCast( lhs ) <= opCast( rhs ) ); |
|
1365 |
} |
||
1366 |
}; |
||
1367 |
|||
1368 |
template<Operator Op, typename T1, typename T2> |
||
1369 |
bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { |
||
1370 |
771 |
return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); |
|
1371 |
} |
||
1372 |
|||
1373 |
// This level of indirection allows us to specialise for integer types |
||
1374 |
// to avoid signed/ unsigned warnings |
||
1375 |
|||
1376 |
// "base" overload |
||
1377 |
template<Operator Op, typename T1, typename T2> |
||
1378 |
bool compare( T1 const& lhs, T2 const& rhs ) { |
||
1379 |
1421270 |
return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); |
|
1380 |
} |
||
1381 |
|||
1382 |
// unsigned X to int |
||
1383 |
template<Operator Op> bool compare( unsigned int lhs, int rhs ) { |
||
1384 |
114 |
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); |
|
1385 |
} |
||
1386 |
template<Operator Op> bool compare( unsigned long lhs, int rhs ) { |
||
1387 |
426 |
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); |
|
1388 |
} |
||
1389 |
template<Operator Op> bool compare( unsigned char lhs, int rhs ) { |
||
1390 |
144 |
return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); |
|
1391 |
} |
||
1392 |
|||
1393 |
// unsigned X to long |
||
1394 |
template<Operator Op> bool compare( unsigned int lhs, long rhs ) { |
||
1395 |
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); |
||
1396 |
} |
||
1397 |
template<Operator Op> bool compare( unsigned long lhs, long rhs ) { |
||
1398 |
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); |
||
1399 |
} |
||
1400 |
template<Operator Op> bool compare( unsigned char lhs, long rhs ) { |
||
1401 |
return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); |
||
1402 |
} |
||
1403 |
|||
1404 |
// int to unsigned X |
||
1405 |
template<Operator Op> bool compare( int lhs, unsigned int rhs ) { |
||
1406 |
60 |
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); |
|
1407 |
} |
||
1408 |
template<Operator Op> bool compare( int lhs, unsigned long rhs ) { |
||
1409 |
27 |
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); |
|
1410 |
} |
||
1411 |
template<Operator Op> bool compare( int lhs, unsigned char rhs ) { |
||
1412 |
return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); |
||
1413 |
} |
||
1414 |
|||
1415 |
// long to unsigned X |
||
1416 |
template<Operator Op> bool compare( long lhs, unsigned int rhs ) { |
||
1417 |
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); |
||
1418 |
} |
||
1419 |
template<Operator Op> bool compare( long lhs, unsigned long rhs ) { |
||
1420 |
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); |
||
1421 |
} |
||
1422 |
template<Operator Op> bool compare( long lhs, unsigned char rhs ) { |
||
1423 |
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); |
||
1424 |
} |
||
1425 |
|||
1426 |
// pointer to long (when comparing against NULL) |
||
1427 |
template<Operator Op, typename T> bool compare( long lhs, T* rhs ) { |
||
1428 |
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); |
||
1429 |
} |
||
1430 |
template<Operator Op, typename T> bool compare( T* lhs, long rhs ) { |
||
1431 |
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); |
||
1432 |
} |
||
1433 |
|||
1434 |
// pointer to int (when comparing against NULL) |
||
1435 |
template<Operator Op, typename T> bool compare( int lhs, T* rhs ) { |
||
1436 |
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); |
||
1437 |
} |
||
1438 |
template<Operator Op, typename T> bool compare( T* lhs, int rhs ) { |
||
1439 |
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); |
||
1440 |
} |
||
1441 |
|||
1442 |
#ifdef CATCH_CONFIG_CPP11_LONG_LONG |
||
1443 |
// long long to unsigned X |
||
1444 |
template<Operator Op> bool compare( long long lhs, unsigned int rhs ) { |
||
1445 |
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); |
||
1446 |
} |
||
1447 |
template<Operator Op> bool compare( long long lhs, unsigned long rhs ) { |
||
1448 |
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); |
||
1449 |
} |
||
1450 |
template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) { |
||
1451 |
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); |
||
1452 |
} |
||
1453 |
template<Operator Op> bool compare( long long lhs, unsigned char rhs ) { |
||
1454 |
return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); |
||
1455 |
} |
||
1456 |
|||
1457 |
// unsigned long long to X |
||
1458 |
template<Operator Op> bool compare( unsigned long long lhs, int rhs ) { |
||
1459 |
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); |
||
1460 |
} |
||
1461 |
template<Operator Op> bool compare( unsigned long long lhs, long rhs ) { |
||
1462 |
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); |
||
1463 |
} |
||
1464 |
template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) { |
||
1465 |
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); |
||
1466 |
} |
||
1467 |
template<Operator Op> bool compare( unsigned long long lhs, char rhs ) { |
||
1468 |
return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); |
||
1469 |
} |
||
1470 |
|||
1471 |
// pointer to long long (when comparing against NULL) |
||
1472 |
template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) { |
||
1473 |
return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); |
||
1474 |
} |
||
1475 |
template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) { |
||
1476 |
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); |
||
1477 |
} |
||
1478 |
#endif // CATCH_CONFIG_CPP11_LONG_LONG |
||
1479 |
|||
1480 |
#ifdef CATCH_CONFIG_CPP11_NULLPTR |
||
1481 |
// pointer to nullptr_t (when comparing against nullptr) |
||
1482 |
template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) { |
||
1483 |
30 |
return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs ); |
|
1484 |
} |
||
1485 |
template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) { |
||
1486 |
10365 |
return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr ); |
|
1487 |
} |
||
1488 |
#endif // CATCH_CONFIG_CPP11_NULLPTR |
||
1489 |
|||
1490 |
} // end of namespace Internal |
||
1491 |
} // end of namespace Catch |
||
1492 |
|||
1493 |
#ifdef _MSC_VER |
||
1494 |
#pragma warning(pop) |
||
1495 |
#endif |
||
1496 |
|||
1497 |
// #included from: catch_tostring.h |
||
1498 |
#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED |
||
1499 |
|||
1500 |
#include <sstream> |
||
1501 |
#include <iomanip> |
||
1502 |
#include <limits> |
||
1503 |
#include <vector> |
||
1504 |
#include <cstddef> |
||
1505 |
|||
1506 |
#ifdef __OBJC__ |
||
1507 |
// #included from: catch_objc_arc.hpp |
||
1508 |
#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED |
||
1509 |
|||
1510 |
#import <Foundation/Foundation.h> |
||
1511 |
|||
1512 |
#ifdef __has_feature |
||
1513 |
#define CATCH_ARC_ENABLED __has_feature(objc_arc) |
||
1514 |
#else |
||
1515 |
#define CATCH_ARC_ENABLED 0 |
||
1516 |
#endif |
||
1517 |
|||
1518 |
void arcSafeRelease( NSObject* obj ); |
||
1519 |
id performOptionalSelector( id obj, SEL sel ); |
||
1520 |
|||
1521 |
#if !CATCH_ARC_ENABLED |
||
1522 |
inline void arcSafeRelease( NSObject* obj ) { |
||
1523 |
[obj release]; |
||
1524 |
} |
||
1525 |
inline id performOptionalSelector( id obj, SEL sel ) { |
||
1526 |
if( [obj respondsToSelector: sel] ) |
||
1527 |
return [obj performSelector: sel]; |
||
1528 |
return nil; |
||
1529 |
} |
||
1530 |
#define CATCH_UNSAFE_UNRETAINED |
||
1531 |
#define CATCH_ARC_STRONG |
||
1532 |
#else |
||
1533 |
inline void arcSafeRelease( NSObject* ){} |
||
1534 |
inline id performOptionalSelector( id obj, SEL sel ) { |
||
1535 |
#ifdef __clang__ |
||
1536 |
#pragma clang diagnostic push |
||
1537 |
#pragma clang diagnostic ignored "-Warc-performSelector-leaks" |
||
1538 |
#endif |
||
1539 |
if( [obj respondsToSelector: sel] ) |
||
1540 |
return [obj performSelector: sel]; |
||
1541 |
#ifdef __clang__ |
||
1542 |
#pragma clang diagnostic pop |
||
1543 |
#endif |
||
1544 |
return nil; |
||
1545 |
} |
||
1546 |
#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained |
||
1547 |
#define CATCH_ARC_STRONG __strong |
||
1548 |
#endif |
||
1549 |
|||
1550 |
#endif |
||
1551 |
|||
1552 |
#ifdef CATCH_CONFIG_CPP11_TUPLE |
||
1553 |
#include <tuple> |
||
1554 |
#endif |
||
1555 |
|||
1556 |
#ifdef CATCH_CONFIG_CPP11_IS_ENUM |
||
1557 |
#include <type_traits> |
||
1558 |
#endif |
||
1559 |
|||
1560 |
namespace Catch { |
||
1561 |
|||
1562 |
// Why we're here. |
||
1563 |
template<typename T> |
||
1564 |
std::string toString( T const& value ); |
||
1565 |
|||
1566 |
// Built in overloads |
||
1567 |
|||
1568 |
std::string toString( std::string const& value ); |
||
1569 |
std::string toString( std::wstring const& value ); |
||
1570 |
std::string toString( const char* const value ); |
||
1571 |
std::string toString( char* const value ); |
||
1572 |
std::string toString( const wchar_t* const value ); |
||
1573 |
std::string toString( wchar_t* const value ); |
||
1574 |
std::string toString( int value ); |
||
1575 |
std::string toString( unsigned long value ); |
||
1576 |
std::string toString( unsigned int value ); |
||
1577 |
std::string toString( const double value ); |
||
1578 |
std::string toString( const float value ); |
||
1579 |
std::string toString( bool value ); |
||
1580 |
std::string toString( char value ); |
||
1581 |
std::string toString( signed char value ); |
||
1582 |
std::string toString( unsigned char value ); |
||
1583 |
|||
1584 |
#ifdef CATCH_CONFIG_CPP11_LONG_LONG |
||
1585 |
std::string toString( long long value ); |
||
1586 |
std::string toString( unsigned long long value ); |
||
1587 |
#endif |
||
1588 |
|||
1589 |
#ifdef CATCH_CONFIG_CPP11_NULLPTR |
||
1590 |
std::string toString( std::nullptr_t ); |
||
1591 |
#endif |
||
1592 |
|||
1593 |
#ifdef __OBJC__ |
||
1594 |
std::string toString( NSString const * const& nsstring ); |
||
1595 |
std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); |
||
1596 |
std::string toString( NSObject* const& nsObject ); |
||
1597 |
#endif |
||
1598 |
|||
1599 |
namespace Detail { |
||
1600 |
|||
1601 |
extern const std::string unprintableString; |
||
1602 |
|||
1603 |
struct BorgType { |
||
1604 |
template<typename T> BorgType( T const& ); |
||
1605 |
}; |
||
1606 |
|||
1607 |
struct TrueType { char sizer[1]; }; |
||
1608 |
struct FalseType { char sizer[2]; }; |
||
1609 |
|||
1610 |
TrueType& testStreamable( std::ostream& ); |
||
1611 |
FalseType testStreamable( FalseType ); |
||
1612 |
|||
1613 |
FalseType operator<<( std::ostream const&, BorgType const& ); |
||
1614 |
|||
1615 |
template<typename T> |
||
1616 |
struct IsStreamInsertable { |
||
1617 |
static std::ostream &s; |
||
1618 |
static T const&t; |
||
1619 |
enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; |
||
1620 |
}; |
||
1621 |
|||
1622 |
#if defined(CATCH_CONFIG_CPP11_IS_ENUM) |
||
1623 |
template<typename T, |
||
1624 |
bool IsEnum = std::is_enum<T>::value |
||
1625 |
> |
||
1626 |
struct EnumStringMaker |
||
1627 |
{ |
||
1628 |
74 |
static std::string convert( T const& ) { return unprintableString; } |
|
1629 |
}; |
||
1630 |
|||
1631 |
template<typename T> |
||
1632 |
struct EnumStringMaker<T,true> |
||
1633 |
{ |
||
1634 |
static std::string convert( T const& v ) |
||
1635 |
{ |
||
1636 |
return ::Catch::toString( |
||
1637 |
static_cast<typename std::underlying_type<T>::type>(v) |
||
1638 |
✓✗✓✗ ✓✗✓✗ |
4486 |
); |
1639 |
} |
||
1640 |
}; |
||
1641 |
#endif |
||
1642 |
template<bool C> |
||
1643 |
struct StringMakerBase { |
||
1644 |
#if defined(CATCH_CONFIG_CPP11_IS_ENUM) |
||
1645 |
template<typename T> |
||
1646 |
static std::string convert( T const& v ) |
||
1647 |
{ |
||
1648 |
4560 |
return EnumStringMaker<T>::convert( v ); |
|
1649 |
} |
||
1650 |
#else |
||
1651 |
template<typename T> |
||
1652 |
static std::string convert( T const& ) { return unprintableString; } |
||
1653 |
#endif |
||
1654 |
}; |
||
1655 |
|||
1656 |
template<> |
||
1657 |
struct StringMakerBase<true> { |
||
1658 |
template<typename T> |
||
1659 |
927222 |
static std::string convert( T const& _value ) { |
|
1660 |
1854444 |
std::ostringstream oss; |
|
1661 |
1854444 |
oss << _value; |
|
1662 |
1854444 |
return oss.str(); |
|
1663 |
} |
||
1664 |
}; |
||
1665 |
|||
1666 |
std::string rawMemoryToString( const void *object, std::size_t size ); |
||
1667 |
|||
1668 |
template<typename T> |
||
1669 |
inline std::string rawMemoryToString( const T& object ) { |
||
1670 |
10579 |
return rawMemoryToString( &object, sizeof(object) ); |
|
1671 |
} |
||
1672 |
|||
1673 |
} // end namespace Detail |
||
1674 |
|||
1675 |
template<typename T> |
||
1676 |
struct StringMaker : |
||
1677 |
Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {}; |
||
1678 |
|||
1679 |
template<typename T> |
||
1680 |
struct StringMaker<T*> { |
||
1681 |
template<typename U> |
||
1682 |
10686 |
static std::string convert( U* p ) { |
|
1683 |
✓✓✓✓ ✓✓✗✓ ✗✓ |
10686 |
if( !p ) |
1684 |
287 |
return "NULL"; |
|
1685 |
else |
||
1686 |
return Detail::rawMemoryToString( p ); |
||
1687 |
} |
||
1688 |
}; |
||
1689 |
|||
1690 |
template<typename R, typename C> |
||
1691 |
struct StringMaker<R C::*> { |
||
1692 |
static std::string convert( R C::* p ) { |
||
1693 |
if( !p ) |
||
1694 |
return "NULL"; |
||
1695 |
else |
||
1696 |
return Detail::rawMemoryToString( p ); |
||
1697 |
} |
||
1698 |
}; |
||
1699 |
|||
1700 |
namespace Detail { |
||
1701 |
template<typename InputIterator> |
||
1702 |
std::string rangeToString( InputIterator first, InputIterator last ); |
||
1703 |
} |
||
1704 |
|||
1705 |
//template<typename T, typename Allocator> |
||
1706 |
//struct StringMaker<std::vector<T, Allocator> > { |
||
1707 |
// static std::string convert( std::vector<T,Allocator> const& v ) { |
||
1708 |
// return Detail::rangeToString( v.begin(), v.end() ); |
||
1709 |
// } |
||
1710 |
//}; |
||
1711 |
|||
1712 |
template<typename T, typename Allocator> |
||
1713 |
std::string toString( std::vector<T,Allocator> const& v ) { |
||
1714 |
return Detail::rangeToString( v.begin(), v.end() ); |
||
1715 |
} |
||
1716 |
|||
1717 |
#ifdef CATCH_CONFIG_CPP11_TUPLE |
||
1718 |
|||
1719 |
// toString for tuples |
||
1720 |
namespace TupleDetail { |
||
1721 |
template< |
||
1722 |
typename Tuple, |
||
1723 |
std::size_t N = 0, |
||
1724 |
bool = (N < std::tuple_size<Tuple>::value) |
||
1725 |
> |
||
1726 |
struct ElementPrinter { |
||
1727 |
static void print( const Tuple& tuple, std::ostream& os ) |
||
1728 |
{ |
||
1729 |
os << ( N ? ", " : " " ) |
||
1730 |
<< Catch::toString(std::get<N>(tuple)); |
||
1731 |
ElementPrinter<Tuple,N+1>::print(tuple,os); |
||
1732 |
} |
||
1733 |
}; |
||
1734 |
|||
1735 |
template< |
||
1736 |
typename Tuple, |
||
1737 |
std::size_t N |
||
1738 |
> |
||
1739 |
struct ElementPrinter<Tuple,N,false> { |
||
1740 |
static void print( const Tuple&, std::ostream& ) {} |
||
1741 |
}; |
||
1742 |
|||
1743 |
} |
||
1744 |
|||
1745 |
template<typename ...Types> |
||
1746 |
struct StringMaker<std::tuple<Types...>> { |
||
1747 |
|||
1748 |
static std::string convert( const std::tuple<Types...>& tuple ) |
||
1749 |
{ |
||
1750 |
std::ostringstream os; |
||
1751 |
os << '{'; |
||
1752 |
TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os ); |
||
1753 |
os << " }"; |
||
1754 |
return os.str(); |
||
1755 |
} |
||
1756 |
}; |
||
1757 |
#endif // CATCH_CONFIG_CPP11_TUPLE |
||
1758 |
|||
1759 |
namespace Detail { |
||
1760 |
template<typename T> |
||
1761 |
std::string makeString( T const& value ) { |
||
1762 |
926654 |
return StringMaker<T>::convert( value ); |
|
1763 |
} |
||
1764 |
} // end namespace Detail |
||
1765 |
|||
1766 |
/// \brief converts any type to a string |
||
1767 |
/// |
||
1768 |
/// The default template forwards on to ostringstream - except when an |
||
1769 |
/// ostringstream overload does not exist - in which case it attempts to detect |
||
1770 |
/// that and writes {?}. |
||
1771 |
/// Overload (not specialise) this template for custom typs that you don't want |
||
1772 |
/// to provide an ostream overload for. |
||
1773 |
template<typename T> |
||
1774 |
std::string toString( T const& value ) { |
||
1775 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
15814 |
return StringMaker<T>::convert( value ); |
1776 |
} |
||
1777 |
|||
1778 |
namespace Detail { |
||
1779 |
template<typename InputIterator> |
||
1780 |
std::string rangeToString( InputIterator first, InputIterator last ) { |
||
1781 |
std::ostringstream oss; |
||
1782 |
oss << "{ "; |
||
1783 |
if( first != last ) { |
||
1784 |
oss << Catch::toString( *first ); |
||
1785 |
for( ++first ; first != last ; ++first ) |
||
1786 |
oss << ", " << Catch::toString( *first ); |
||
1787 |
} |
||
1788 |
oss << " }"; |
||
1789 |
return oss.str(); |
||
1790 |
} |
||
1791 |
} |
||
1792 |
|||
1793 |
} // end namespace Catch |
||
1794 |
|||
1795 |
namespace Catch { |
||
1796 |
|||
1797 |
// Wraps the LHS of an expression and captures the operator and RHS (if any) - |
||
1798 |
// wrapping them all in a ResultBuilder object |
||
1799 |
template<typename T> |
||
1800 |
class ExpressionLhs { |
||
1801 |
ExpressionLhs& operator = ( ExpressionLhs const& ); |
||
1802 |
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS |
||
1803 |
ExpressionLhs& operator = ( ExpressionLhs && ) = delete; |
||
1804 |
# endif |
||
1805 |
|||
1806 |
public: |
||
1807 |
81028 |
ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} |
|
1808 |
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS |
||
1809 |
ExpressionLhs( ExpressionLhs const& ) = default; |
||
1810 |
ExpressionLhs( ExpressionLhs && ) = default; |
||
1811 |
# endif |
||
1812 |
|||
1813 |
template<typename RhsT> |
||
1814 |
ResultBuilder& operator == ( RhsT const& rhs ) { |
||
1815 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
1334717 |
return captureExpression<Internal::IsEqualTo>( rhs ); |
1816 |
} |
||
1817 |
|||
1818 |
template<typename RhsT> |
||
1819 |
ResultBuilder& operator != ( RhsT const& rhs ) { |
||
1820 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
10326 |
return captureExpression<Internal::IsNotEqualTo>( rhs ); |
1821 |
} |
||
1822 |
|||
1823 |
template<typename RhsT> |
||
1824 |
ResultBuilder& operator < ( RhsT const& rhs ) { |
||
1825 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗✗✗ |
4031 |
return captureExpression<Internal::IsLessThan>( rhs ); |
1826 |
} |
||
1827 |
|||
1828 |
template<typename RhsT> |
||
1829 |
ResultBuilder& operator > ( RhsT const& rhs ) { |
||
1830 |
✓✗✓✗ ✓✗✓✗ |
2685 |
return captureExpression<Internal::IsGreaterThan>( rhs ); |
1831 |
} |
||
1832 |
|||
1833 |
template<typename RhsT> |
||
1834 |
ResultBuilder& operator <= ( RhsT const& rhs ) { |
||
1835 |
✓✗✓✗ ✓✗✓✗ |
4 |
return captureExpression<Internal::IsLessThanOrEqualTo>( rhs ); |
1836 |
} |
||
1837 |
|||
1838 |
template<typename RhsT> |
||
1839 |
ResultBuilder& operator >= ( RhsT const& rhs ) { |
||
1840 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
22 |
return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs ); |
1841 |
} |
||
1842 |
|||
1843 |
ResultBuilder& operator == ( bool rhs ) { |
||
1844 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
80637 |
return captureExpression<Internal::IsEqualTo>( rhs ); |
1845 |
} |
||
1846 |
|||
1847 |
ResultBuilder& operator != ( bool rhs ) { |
||
1848 |
return captureExpression<Internal::IsNotEqualTo>( rhs ); |
||
1849 |
} |
||
1850 |
|||
1851 |
469 |
void endExpression() { |
|
1852 |
469 |
bool value = m_lhs ? true : false; |
|
1853 |
✓✗✓✗ |
938 |
m_rb |
1854 |
✓✗✓✗ |
1407 |
.setLhs( Catch::toString( value ) ) |
1855 |
✓✗✓✗ |
938 |
.setResultType( value ) |
1856 |
.endExpression(); |
||
1857 |
469 |
} |
|
1858 |
|||
1859 |
// Only simple binary expressions are allowed on the LHS. |
||
1860 |
// If more complex compositions are required then place the sub expression in parentheses |
||
1861 |
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); |
||
1862 |
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); |
||
1863 |
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); |
||
1864 |
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); |
||
1865 |
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); |
||
1866 |
template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); |
||
1867 |
|||
1868 |
private: |
||
1869 |
template<Internal::Operator Op, typename RhsT> |
||
1870 |
1432423 |
ResultBuilder& captureExpression( RhsT const& rhs ) { |
|
1871 |
1432423 |
return m_rb |
|
1872 |
1525643 |
.setResultType( Internal::compare<Op>( m_lhs, rhs ) ) |
|
1873 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✓✗✗✗ ✓✗✓✗ ✗✗✓✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
4283927 |
.setLhs( Catch::toString( m_lhs ) ) |
1874 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✓✗✓✗ ✗✗✗✗ ✓✗✓✗ ✗✗✗✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
4297767 |
.setRhs( Catch::toString( rhs ) ) |
1875 |
✓✗✓✗ ✓✓✗✓ ✗✓✗✓ ✓✗✓✗ ✓✓✗✓ ✓✗✓✗ ✓✗✗✓ ✓✗✓✗ ✓✓✗✓ ✓✗✓✓ ✗✓✓✗ ✓✓✗✗ ✓✗✗✓ ✗✗✓✓ ✗✓✗✓ ✗✓✓✗ ✓✗✓✗ ✓✗✗✓ ✗✓✗✓ ✓✗✓✗ ✓✗✓✓ ✗✓✗✓ ✗✓✓✗ ✓✗✓✗ ✓✓✗✓ ✗✓✓✗ ✓✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✗✗✗ ✗✗✗✓ ✗✓✗✓ ✗✗✗✗ ✗✗✗✓ ✗✓✗✓ ✗✓✗✗ ✗✗✗✗ ✗✓✗✓ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗ |
8594608 |
.setOp( Internal::OperatorTraits<Op>::getName() ); |
1876 |
} |
||
1877 |
|||
1878 |
private: |
||
1879 |
ResultBuilder& m_rb; |
||
1880 |
T m_lhs; |
||
1881 |
}; |
||
1882 |
|||
1883 |
} // end namespace Catch |
||
1884 |
|||
1885 |
|||
1886 |
namespace Catch { |
||
1887 |
|||
1888 |
template<typename T> |
||
1889 |
inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) { |
||
1890 |
1351823 |
return ExpressionLhs<T const&>( *this, operand ); |
|
1891 |
} |
||
1892 |
|||
1893 |
inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) { |
||
1894 |
162096 |
return ExpressionLhs<bool>( *this, value ); |
|
1895 |
} |
||
1896 |
|||
1897 |
} // namespace Catch |
||
1898 |
|||
1899 |
// #included from: catch_message.h |
||
1900 |
#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED |
||
1901 |
|||
1902 |
#include <string> |
||
1903 |
|||
1904 |
namespace Catch { |
||
1905 |
|||
1906 |
struct MessageInfo { |
||
1907 |
MessageInfo( std::string const& _macroName, |
||
1908 |
SourceLineInfo const& _lineInfo, |
||
1909 |
ResultWas::OfType _type ); |
||
1910 |
|||
1911 |
std::string macroName; |
||
1912 |
SourceLineInfo lineInfo; |
||
1913 |
ResultWas::OfType type; |
||
1914 |
std::string message; |
||
1915 |
unsigned int sequence; |
||
1916 |
|||
1917 |
bool operator == ( MessageInfo const& other ) const { |
||
1918 |
return sequence == other.sequence; |
||
1919 |
} |
||
1920 |
bool operator < ( MessageInfo const& other ) const { |
||
1921 |
return sequence < other.sequence; |
||
1922 |
} |
||
1923 |
private: |
||
1924 |
static unsigned int globalCount; |
||
1925 |
}; |
||
1926 |
|||
1927 |
struct MessageBuilder { |
||
1928 |
MessageBuilder( std::string const& macroName, |
||
1929 |
SourceLineInfo const& lineInfo, |
||
1930 |
ResultWas::OfType type ) |
||
1931 |
: m_info( macroName, lineInfo, type ) |
||
1932 |
{} |
||
1933 |
|||
1934 |
template<typename T> |
||
1935 |
MessageBuilder& operator << ( T const& value ) { |
||
1936 |
m_stream << value; |
||
1937 |
return *this; |
||
1938 |
} |
||
1939 |
|||
1940 |
MessageInfo m_info; |
||
1941 |
std::ostringstream m_stream; |
||
1942 |
}; |
||
1943 |
|||
1944 |
class ScopedMessage { |
||
1945 |
public: |
||
1946 |
ScopedMessage( MessageBuilder const& builder ); |
||
1947 |
ScopedMessage( ScopedMessage const& other ); |
||
1948 |
~ScopedMessage(); |
||
1949 |
|||
1950 |
MessageInfo m_info; |
||
1951 |
}; |
||
1952 |
|||
1953 |
} // end namespace Catch |
||
1954 |
|||
1955 |
// #included from: catch_interfaces_capture.h |
||
1956 |
#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED |
||
1957 |
|||
1958 |
#include <string> |
||
1959 |
|||
1960 |
namespace Catch { |
||
1961 |
|||
1962 |
class TestCase; |
||
1963 |
class AssertionResult; |
||
1964 |
struct AssertionInfo; |
||
1965 |
struct SectionInfo; |
||
1966 |
struct SectionEndInfo; |
||
1967 |
struct MessageInfo; |
||
1968 |
class ScopedMessageBuilder; |
||
1969 |
struct Counts; |
||
1970 |
|||
1971 |
struct IResultCapture { |
||
1972 |
|||
1973 |
virtual ~IResultCapture(); |
||
1974 |
|||
1975 |
virtual void assertionEnded( AssertionResult const& result ) = 0; |
||
1976 |
virtual bool sectionStarted( SectionInfo const& sectionInfo, |
||
1977 |
Counts& assertions ) = 0; |
||
1978 |
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; |
||
1979 |
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; |
||
1980 |
virtual void pushScopedMessage( MessageInfo const& message ) = 0; |
||
1981 |
virtual void popScopedMessage( MessageInfo const& message ) = 0; |
||
1982 |
|||
1983 |
virtual std::string getCurrentTestName() const = 0; |
||
1984 |
virtual const AssertionResult* getLastResult() const = 0; |
||
1985 |
|||
1986 |
virtual void handleFatalErrorCondition( std::string const& message ) = 0; |
||
1987 |
}; |
||
1988 |
|||
1989 |
IResultCapture& getResultCapture(); |
||
1990 |
} |
||
1991 |
|||
1992 |
// #included from: catch_debugger.h |
||
1993 |
#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED |
||
1994 |
|||
1995 |
// #included from: catch_platform.h |
||
1996 |
#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED |
||
1997 |
|||
1998 |
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) |
||
1999 |
#define CATCH_PLATFORM_MAC |
||
2000 |
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) |
||
2001 |
#define CATCH_PLATFORM_IPHONE |
||
2002 |
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) |
||
2003 |
#define CATCH_PLATFORM_WINDOWS |
||
2004 |
#endif |
||
2005 |
|||
2006 |
#include <string> |
||
2007 |
|||
2008 |
namespace Catch{ |
||
2009 |
|||
2010 |
bool isDebuggerActive(); |
||
2011 |
void writeToDebugConsole( std::string const& text ); |
||
2012 |
} |
||
2013 |
|||
2014 |
#ifdef CATCH_PLATFORM_MAC |
||
2015 |
|||
2016 |
// The following code snippet based on: |
||
2017 |
// http://cocoawithlove.com/2008/03/break-into-debugger.html |
||
2018 |
#ifdef DEBUG |
||
2019 |
#if defined(__ppc64__) || defined(__ppc__) |
||
2020 |
#define CATCH_BREAK_INTO_DEBUGGER() \ |
||
2021 |
if( Catch::isDebuggerActive() ) { \ |
||
2022 |
__asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ |
||
2023 |
: : : "memory","r0","r3","r4" ); \ |
||
2024 |
} |
||
2025 |
#else |
||
2026 |
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} |
||
2027 |
#endif |
||
2028 |
#endif |
||
2029 |
|||
2030 |
#elif defined(_MSC_VER) |
||
2031 |
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } |
||
2032 |
#elif defined(__MINGW32__) |
||
2033 |
extern "C" __declspec(dllimport) void __stdcall DebugBreak(); |
||
2034 |
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } |
||
2035 |
#endif |
||
2036 |
|||
2037 |
#ifndef CATCH_BREAK_INTO_DEBUGGER |
||
2038 |
#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); |
||
2039 |
#endif |
||
2040 |
|||
2041 |
// #included from: catch_interfaces_runner.h |
||
2042 |
#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED |
||
2043 |
|||
2044 |
namespace Catch { |
||
2045 |
class TestCase; |
||
2046 |
|||
2047 |
struct IRunner { |
||
2048 |
virtual ~IRunner(); |
||
2049 |
virtual bool aborting() const = 0; |
||
2050 |
}; |
||
2051 |
} |
||
2052 |
|||
2053 |
/////////////////////////////////////////////////////////////////////////////// |
||
2054 |
// In the event of a failure works out if the debugger needs to be invoked |
||
2055 |
// and/or an exception thrown and takes appropriate action. |
||
2056 |
// This needs to be done as a macro so the debugger will stop in the user |
||
2057 |
// source code rather than in Catch library code |
||
2058 |
#define INTERNAL_CATCH_REACT( resultBuilder ) \ |
||
2059 |
if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ |
||
2060 |
resultBuilder.react(); |
||
2061 |
|||
2062 |
/////////////////////////////////////////////////////////////////////////////// |
||
2063 |
#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ |
||
2064 |
do { \ |
||
2065 |
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ |
||
2066 |
try { \ |
||
2067 |
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ |
||
2068 |
( __catchResult <= expr ).endExpression(); \ |
||
2069 |
} \ |
||
2070 |
catch( ... ) { \ |
||
2071 |
__catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ |
||
2072 |
} \ |
||
2073 |
INTERNAL_CATCH_REACT( __catchResult ) \ |
||
2074 |
} 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 |
||
2075 |
|||
2076 |
/////////////////////////////////////////////////////////////////////////////// |
||
2077 |
#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ |
||
2078 |
INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ |
||
2079 |
if( Catch::getResultCapture().getLastResult()->succeeded() ) |
||
2080 |
|||
2081 |
/////////////////////////////////////////////////////////////////////////////// |
||
2082 |
#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ |
||
2083 |
INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ |
||
2084 |
if( !Catch::getResultCapture().getLastResult()->succeeded() ) |
||
2085 |
|||
2086 |
/////////////////////////////////////////////////////////////////////////////// |
||
2087 |
#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ |
||
2088 |
do { \ |
||
2089 |
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ |
||
2090 |
try { \ |
||
2091 |
expr; \ |
||
2092 |
__catchResult.captureResult( Catch::ResultWas::Ok ); \ |
||
2093 |
} \ |
||
2094 |
catch( ... ) { \ |
||
2095 |
__catchResult.useActiveException( resultDisposition ); \ |
||
2096 |
} \ |
||
2097 |
INTERNAL_CATCH_REACT( __catchResult ) \ |
||
2098 |
} while( Catch::alwaysFalse() ) |
||
2099 |
|||
2100 |
/////////////////////////////////////////////////////////////////////////////// |
||
2101 |
#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ |
||
2102 |
do { \ |
||
2103 |
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ |
||
2104 |
if( __catchResult.allowThrows() ) \ |
||
2105 |
try { \ |
||
2106 |
expr; \ |
||
2107 |
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ |
||
2108 |
} \ |
||
2109 |
catch( ... ) { \ |
||
2110 |
__catchResult.captureExpectedException( matcher ); \ |
||
2111 |
} \ |
||
2112 |
else \ |
||
2113 |
__catchResult.captureResult( Catch::ResultWas::Ok ); \ |
||
2114 |
INTERNAL_CATCH_REACT( __catchResult ) \ |
||
2115 |
} while( Catch::alwaysFalse() ) |
||
2116 |
|||
2117 |
/////////////////////////////////////////////////////////////////////////////// |
||
2118 |
#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ |
||
2119 |
do { \ |
||
2120 |
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ |
||
2121 |
if( __catchResult.allowThrows() ) \ |
||
2122 |
try { \ |
||
2123 |
expr; \ |
||
2124 |
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ |
||
2125 |
} \ |
||
2126 |
catch( exceptionType ) { \ |
||
2127 |
__catchResult.captureResult( Catch::ResultWas::Ok ); \ |
||
2128 |
} \ |
||
2129 |
catch( ... ) { \ |
||
2130 |
__catchResult.useActiveException( resultDisposition ); \ |
||
2131 |
} \ |
||
2132 |
else \ |
||
2133 |
__catchResult.captureResult( Catch::ResultWas::Ok ); \ |
||
2134 |
INTERNAL_CATCH_REACT( __catchResult ) \ |
||
2135 |
} while( Catch::alwaysFalse() ) |
||
2136 |
|||
2137 |
/////////////////////////////////////////////////////////////////////////////// |
||
2138 |
#ifdef CATCH_CONFIG_VARIADIC_MACROS |
||
2139 |
#define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ |
||
2140 |
do { \ |
||
2141 |
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ |
||
2142 |
__catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ |
||
2143 |
__catchResult.captureResult( messageType ); \ |
||
2144 |
INTERNAL_CATCH_REACT( __catchResult ) \ |
||
2145 |
} while( Catch::alwaysFalse() ) |
||
2146 |
#else |
||
2147 |
#define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ |
||
2148 |
do { \ |
||
2149 |
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ |
||
2150 |
__catchResult << log + ::Catch::StreamEndStop(); \ |
||
2151 |
__catchResult.captureResult( messageType ); \ |
||
2152 |
INTERNAL_CATCH_REACT( __catchResult ) \ |
||
2153 |
} while( Catch::alwaysFalse() ) |
||
2154 |
#endif |
||
2155 |
|||
2156 |
/////////////////////////////////////////////////////////////////////////////// |
||
2157 |
#define INTERNAL_CATCH_INFO( log, macroName ) \ |
||
2158 |
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; |
||
2159 |
|||
2160 |
/////////////////////////////////////////////////////////////////////////////// |
||
2161 |
#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ |
||
2162 |
do { \ |
||
2163 |
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ |
||
2164 |
try { \ |
||
2165 |
std::string matcherAsString = (matcher).toString(); \ |
||
2166 |
__catchResult \ |
||
2167 |
.setLhs( Catch::toString( arg ) ) \ |
||
2168 |
.setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ |
||
2169 |
.setOp( "matches" ) \ |
||
2170 |
.setResultType( (matcher).match( arg ) ); \ |
||
2171 |
__catchResult.captureExpression(); \ |
||
2172 |
} catch( ... ) { \ |
||
2173 |
__catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ |
||
2174 |
} \ |
||
2175 |
INTERNAL_CATCH_REACT( __catchResult ) \ |
||
2176 |
} while( Catch::alwaysFalse() ) |
||
2177 |
|||
2178 |
// #included from: internal/catch_section.h |
||
2179 |
#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED |
||
2180 |
|||
2181 |
// #included from: catch_section_info.h |
||
2182 |
#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED |
||
2183 |
|||
2184 |
// #included from: catch_totals.hpp |
||
2185 |
#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED |
||
2186 |
|||
2187 |
#include <cstddef> |
||
2188 |
|||
2189 |
namespace Catch { |
||
2190 |
|||
2191 |
struct Counts { |
||
2192 |
10207 |
Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} |
|
2193 |
|||
2194 |
Counts operator - ( Counts const& other ) const { |
||
2195 |
1933 |
Counts diff; |
|
2196 |
1933 |
diff.passed = passed - other.passed; |
|
2197 |
1933 |
diff.failed = failed - other.failed; |
|
2198 |
1933 |
diff.failedButOk = failedButOk - other.failedButOk; |
|
2199 |
return diff; |
||
2200 |
} |
||
2201 |
Counts& operator += ( Counts const& other ) { |
||
2202 |
1182 |
passed += other.passed; |
|
2203 |
1182 |
failed += other.failed; |
|
2204 |
1182 |
failedButOk += other.failedButOk; |
|
2205 |
return *this; |
||
2206 |
} |
||
2207 |
|||
2208 |
std::size_t total() const { |
||
2209 |
1148 |
return passed + failed + failedButOk; |
|
2210 |
} |
||
2211 |
bool allPassed() const { |
||
2212 |
✓✗✗✓ ✓✗✗✓ |
2 |
return failed == 0 && failedButOk == 0; |
2213 |
} |
||
2214 |
bool allOk() const { |
||
2215 |
return failed == 0; |
||
2216 |
} |
||
2217 |
|||
2218 |
std::size_t passed; |
||
2219 |
std::size_t failed; |
||
2220 |
std::size_t failedButOk; |
||
2221 |
}; |
||
2222 |
|||
2223 |
1188 |
struct Totals { |
|
2224 |
|||
2225 |
Totals operator - ( Totals const& other ) const { |
||
2226 |
394 |
Totals diff; |
|
2227 |
788 |
diff.assertions = assertions - other.assertions; |
|
2228 |
788 |
diff.testCases = testCases - other.testCases; |
|
2229 |
return diff; |
||
2230 |
} |
||
2231 |
|||
2232 |
394 |
Totals delta( Totals const& prevTotals ) const { |
|
2233 |
394 |
Totals diff = *this - prevTotals; |
|
2234 |
✗✓ | 394 |
if( diff.assertions.failed > 0 ) |
2235 |
++diff.testCases.failed; |
||
2236 |
✗✓ | 394 |
else if( diff.assertions.failedButOk > 0 ) |
2237 |
++diff.testCases.failedButOk; |
||
2238 |
else |
||
2239 |
394 |
++diff.testCases.passed; |
|
2240 |
394 |
return diff; |
|
2241 |
} |
||
2242 |
|||
2243 |
Totals& operator += ( Totals const& other ) { |
||
2244 |
788 |
assertions += other.assertions; |
|
2245 |
788 |
testCases += other.testCases; |
|
2246 |
return *this; |
||
2247 |
} |
||
2248 |
|||
2249 |
Counts assertions; |
||
2250 |
Counts testCases; |
||
2251 |
}; |
||
2252 |
} |
||
2253 |
|||
2254 |
namespace Catch { |
||
2255 |
|||
2256 |
123748 |
struct SectionInfo { |
|
2257 |
SectionInfo |
||
2258 |
( SourceLineInfo const& _lineInfo, |
||
2259 |
std::string const& _name, |
||
2260 |
std::string const& _description = std::string() ); |
||
2261 |
|||
2262 |
std::string name; |
||
2263 |
std::string description; |
||
2264 |
SourceLineInfo lineInfo; |
||
2265 |
}; |
||
2266 |
|||
2267 |
✗✗ | 400 |
struct SectionEndInfo { |
2268 |
SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) |
||
2269 |
400 |
: sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) |
|
2270 |
{} |
||
2271 |
|||
2272 |
SectionInfo sectionInfo; |
||
2273 |
Counts prevAssertions; |
||
2274 |
double durationInSeconds; |
||
2275 |
}; |
||
2276 |
|||
2277 |
} // end namespace Catch |
||
2278 |
|||
2279 |
// #included from: catch_timer.h |
||
2280 |
#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED |
||
2281 |
|||
2282 |
#ifdef CATCH_PLATFORM_WINDOWS |
||
2283 |
typedef unsigned long long uint64_t; |
||
2284 |
#else |
||
2285 |
#include <stdint.h> |
||
2286 |
#endif |
||
2287 |
|||
2288 |
namespace Catch { |
||
2289 |
|||
2290 |
class Timer { |
||
2291 |
public: |
||
2292 |
9015 |
Timer() : m_ticks( 0 ) {} |
|
2293 |
void start(); |
||
2294 |
unsigned int getElapsedMicroseconds() const; |
||
2295 |
unsigned int getElapsedMilliseconds() const; |
||
2296 |
double getElapsedSeconds() const; |
||
2297 |
|||
2298 |
private: |
||
2299 |
uint64_t m_ticks; |
||
2300 |
}; |
||
2301 |
|||
2302 |
} // namespace Catch |
||
2303 |
|||
2304 |
#include <string> |
||
2305 |
|||
2306 |
namespace Catch { |
||
2307 |
|||
2308 |
class Section : NonCopyable { |
||
2309 |
public: |
||
2310 |
Section( SectionInfo const& info ); |
||
2311 |
~Section(); |
||
2312 |
|||
2313 |
// This indicates whether the section should be executed or not |
||
2314 |
operator bool() const; |
||
2315 |
|||
2316 |
private: |
||
2317 |
SectionInfo m_info; |
||
2318 |
|||
2319 |
std::string m_name; |
||
2320 |
Counts m_assertions; |
||
2321 |
bool m_sectionIncluded; |
||
2322 |
Timer m_timer; |
||
2323 |
}; |
||
2324 |
|||
2325 |
} // end namespace Catch |
||
2326 |
|||
2327 |
#ifdef CATCH_CONFIG_VARIADIC_MACROS |
||
2328 |
#define INTERNAL_CATCH_SECTION( ... ) \ |
||
2329 |
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) |
||
2330 |
#else |
||
2331 |
#define INTERNAL_CATCH_SECTION( name, desc ) \ |
||
2332 |
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) |
||
2333 |
#endif |
||
2334 |
|||
2335 |
// #included from: internal/catch_generators.hpp |
||
2336 |
#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED |
||
2337 |
|||
2338 |
#include <iterator> |
||
2339 |
#include <vector> |
||
2340 |
#include <string> |
||
2341 |
#include <stdlib.h> |
||
2342 |
|||
2343 |
namespace Catch { |
||
2344 |
|||
2345 |
template<typename T> |
||
2346 |
struct IGenerator { |
||
2347 |
virtual ~IGenerator() {} |
||
2348 |
virtual T getValue( std::size_t index ) const = 0; |
||
2349 |
virtual std::size_t size () const = 0; |
||
2350 |
}; |
||
2351 |
|||
2352 |
template<typename T> |
||
2353 |
class BetweenGenerator : public IGenerator<T> { |
||
2354 |
public: |
||
2355 |
BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} |
||
2356 |
|||
2357 |
virtual T getValue( std::size_t index ) const { |
||
2358 |
return m_from+static_cast<int>( index ); |
||
2359 |
} |
||
2360 |
|||
2361 |
virtual std::size_t size() const { |
||
2362 |
return static_cast<std::size_t>( 1+m_to-m_from ); |
||
2363 |
} |
||
2364 |
|||
2365 |
private: |
||
2366 |
|||
2367 |
T m_from; |
||
2368 |
T m_to; |
||
2369 |
}; |
||
2370 |
|||
2371 |
template<typename T> |
||
2372 |
class ValuesGenerator : public IGenerator<T> { |
||
2373 |
public: |
||
2374 |
ValuesGenerator(){} |
||
2375 |
|||
2376 |
void add( T value ) { |
||
2377 |
m_values.push_back( value ); |
||
2378 |
} |
||
2379 |
|||
2380 |
virtual T getValue( std::size_t index ) const { |
||
2381 |
return m_values[index]; |
||
2382 |
} |
||
2383 |
|||
2384 |
virtual std::size_t size() const { |
||
2385 |
return m_values.size(); |
||
2386 |
} |
||
2387 |
|||
2388 |
private: |
||
2389 |
std::vector<T> m_values; |
||
2390 |
}; |
||
2391 |
|||
2392 |
template<typename T> |
||
2393 |
class CompositeGenerator { |
||
2394 |
public: |
||
2395 |
CompositeGenerator() : m_totalSize( 0 ) {} |
||
2396 |
|||
2397 |
// *** Move semantics, similar to auto_ptr *** |
||
2398 |
CompositeGenerator( CompositeGenerator& other ) |
||
2399 |
: m_fileInfo( other.m_fileInfo ), |
||
2400 |
m_totalSize( 0 ) |
||
2401 |
{ |
||
2402 |
move( other ); |
||
2403 |
} |
||
2404 |
|||
2405 |
CompositeGenerator& setFileInfo( const char* fileInfo ) { |
||
2406 |
m_fileInfo = fileInfo; |
||
2407 |
return *this; |
||
2408 |
} |
||
2409 |
|||
2410 |
~CompositeGenerator() { |
||
2411 |
deleteAll( m_composed ); |
||
2412 |
} |
||
2413 |
|||
2414 |
operator T () const { |
||
2415 |
size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); |
||
2416 |
|||
2417 |
typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin(); |
||
2418 |
typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end(); |
||
2419 |
for( size_t index = 0; it != itEnd; ++it ) |
||
2420 |
{ |
||
2421 |
const IGenerator<T>* generator = *it; |
||
2422 |
if( overallIndex >= index && overallIndex < index + generator->size() ) |
||
2423 |
{ |
||
2424 |
return generator->getValue( overallIndex-index ); |
||
2425 |
} |
||
2426 |
index += generator->size(); |
||
2427 |
} |
||
2428 |
CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); |
||
2429 |
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 |
||
2430 |
} |
||
2431 |
|||
2432 |
void add( const IGenerator<T>* generator ) { |
||
2433 |
m_totalSize += generator->size(); |
||
2434 |
m_composed.push_back( generator ); |
||
2435 |
} |
||
2436 |
|||
2437 |
CompositeGenerator& then( CompositeGenerator& other ) { |
||
2438 |
move( other ); |
||
2439 |
return *this; |
||
2440 |
} |
||
2441 |
|||
2442 |
CompositeGenerator& then( T value ) { |
||
2443 |
ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); |
||
2444 |
valuesGen->add( value ); |
||
2445 |
add( valuesGen ); |
||
2446 |
return *this; |
||
2447 |
} |
||
2448 |
|||
2449 |
private: |
||
2450 |
|||
2451 |
void move( CompositeGenerator& other ) { |
||
2452 |
std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); |
||
2453 |
m_totalSize += other.m_totalSize; |
||
2454 |
other.m_composed.clear(); |
||
2455 |
} |
||
2456 |
|||
2457 |
std::vector<const IGenerator<T>*> m_composed; |
||
2458 |
std::string m_fileInfo; |
||
2459 |
size_t m_totalSize; |
||
2460 |
}; |
||
2461 |
|||
2462 |
namespace Generators |
||
2463 |
{ |
||
2464 |
template<typename T> |
||
2465 |
CompositeGenerator<T> between( T from, T to ) { |
||
2466 |
CompositeGenerator<T> generators; |
||
2467 |
generators.add( new BetweenGenerator<T>( from, to ) ); |
||
2468 |
return generators; |
||
2469 |
} |
||
2470 |
|||
2471 |
template<typename T> |
||
2472 |
CompositeGenerator<T> values( T val1, T val2 ) { |
||
2473 |
CompositeGenerator<T> generators; |
||
2474 |
ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); |
||
2475 |
valuesGen->add( val1 ); |
||
2476 |
valuesGen->add( val2 ); |
||
2477 |
generators.add( valuesGen ); |
||
2478 |
return generators; |
||
2479 |
} |
||
2480 |
|||
2481 |
template<typename T> |
||
2482 |
CompositeGenerator<T> values( T val1, T val2, T val3 ){ |
||
2483 |
CompositeGenerator<T> generators; |
||
2484 |
ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); |
||
2485 |
valuesGen->add( val1 ); |
||
2486 |
valuesGen->add( val2 ); |
||
2487 |
valuesGen->add( val3 ); |
||
2488 |
generators.add( valuesGen ); |
||
2489 |
return generators; |
||
2490 |
} |
||
2491 |
|||
2492 |
template<typename T> |
||
2493 |
CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) { |
||
2494 |
CompositeGenerator<T> generators; |
||
2495 |
ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); |
||
2496 |
valuesGen->add( val1 ); |
||
2497 |
valuesGen->add( val2 ); |
||
2498 |
valuesGen->add( val3 ); |
||
2499 |
valuesGen->add( val4 ); |
||
2500 |
generators.add( valuesGen ); |
||
2501 |
return generators; |
||
2502 |
} |
||
2503 |
|||
2504 |
} // end namespace Generators |
||
2505 |
|||
2506 |
using namespace Generators; |
||
2507 |
|||
2508 |
} // end namespace Catch |
||
2509 |
|||
2510 |
#define INTERNAL_CATCH_LINESTR2( line ) #line |
||
2511 |
#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) |
||
2512 |
|||
2513 |
#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) |
||
2514 |
|||
2515 |
// #included from: internal/catch_interfaces_exception.h |
||
2516 |
#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED |
||
2517 |
|||
2518 |
#include <string> |
||
2519 |
#include <vector> |
||
2520 |
|||
2521 |
// #included from: catch_interfaces_registry_hub.h |
||
2522 |
#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED |
||
2523 |
|||
2524 |
#include <string> |
||
2525 |
|||
2526 |
namespace Catch { |
||
2527 |
|||
2528 |
class TestCase; |
||
2529 |
struct ITestCaseRegistry; |
||
2530 |
struct IExceptionTranslatorRegistry; |
||
2531 |
struct IExceptionTranslator; |
||
2532 |
struct IReporterRegistry; |
||
2533 |
struct IReporterFactory; |
||
2534 |
|||
2535 |
struct IRegistryHub { |
||
2536 |
virtual ~IRegistryHub(); |
||
2537 |
|||
2538 |
virtual IReporterRegistry const& getReporterRegistry() const = 0; |
||
2539 |
virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; |
||
2540 |
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; |
||
2541 |
}; |
||
2542 |
|||
2543 |
struct IMutableRegistryHub { |
||
2544 |
virtual ~IMutableRegistryHub(); |
||
2545 |
virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0; |
||
2546 |
virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0; |
||
2547 |
virtual void registerTest( TestCase const& testInfo ) = 0; |
||
2548 |
virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; |
||
2549 |
}; |
||
2550 |
|||
2551 |
IRegistryHub& getRegistryHub(); |
||
2552 |
IMutableRegistryHub& getMutableRegistryHub(); |
||
2553 |
void cleanUp(); |
||
2554 |
std::string translateActiveException(); |
||
2555 |
|||
2556 |
} |
||
2557 |
|||
2558 |
namespace Catch { |
||
2559 |
|||
2560 |
typedef std::string(*exceptionTranslateFunction)(); |
||
2561 |
|||
2562 |
struct IExceptionTranslator; |
||
2563 |
typedef std::vector<const IExceptionTranslator*> ExceptionTranslators; |
||
2564 |
|||
2565 |
struct IExceptionTranslator { |
||
2566 |
virtual ~IExceptionTranslator(); |
||
2567 |
virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; |
||
2568 |
}; |
||
2569 |
|||
2570 |
struct IExceptionTranslatorRegistry { |
||
2571 |
virtual ~IExceptionTranslatorRegistry(); |
||
2572 |
|||
2573 |
virtual std::string translateActiveException() const = 0; |
||
2574 |
}; |
||
2575 |
|||
2576 |
class ExceptionTranslatorRegistrar { |
||
2577 |
template<typename T> |
||
2578 |
class ExceptionTranslator : public IExceptionTranslator { |
||
2579 |
public: |
||
2580 |
|||
2581 |
ExceptionTranslator( std::string(*translateFunction)( T& ) ) |
||
2582 |
: m_translateFunction( translateFunction ) |
||
2583 |
{} |
||
2584 |
|||
2585 |
virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { |
||
2586 |
try { |
||
2587 |
if( it == itEnd ) |
||
2588 |
throw; |
||
2589 |
else |
||
2590 |
return (*it)->translate( it+1, itEnd ); |
||
2591 |
} |
||
2592 |
catch( T& ex ) { |
||
2593 |
return m_translateFunction( ex ); |
||
2594 |
} |
||
2595 |
} |
||
2596 |
|||
2597 |
protected: |
||
2598 |
std::string(*m_translateFunction)( T& ); |
||
2599 |
}; |
||
2600 |
|||
2601 |
public: |
||
2602 |
template<typename T> |
||
2603 |
ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { |
||
2604 |
getMutableRegistryHub().registerTranslator |
||
2605 |
( new ExceptionTranslator<T>( translateFunction ) ); |
||
2606 |
} |
||
2607 |
}; |
||
2608 |
} |
||
2609 |
|||
2610 |
/////////////////////////////////////////////////////////////////////////////// |
||
2611 |
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ |
||
2612 |
static std::string translatorName( signature ); \ |
||
2613 |
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ |
||
2614 |
static std::string translatorName( signature ) |
||
2615 |
|||
2616 |
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) |
||
2617 |
|||
2618 |
// #included from: internal/catch_approx.hpp |
||
2619 |
#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED |
||
2620 |
|||
2621 |
#include <cmath> |
||
2622 |
#include <limits> |
||
2623 |
|||
2624 |
namespace Catch { |
||
2625 |
namespace Detail { |
||
2626 |
|||
2627 |
class Approx { |
||
2628 |
public: |
||
2629 |
explicit Approx ( double value ) |
||
2630 |
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ), |
||
2631 |
m_scale( 1.0 ), |
||
2632 |
m_value( value ) |
||
2633 |
{} |
||
2634 |
|||
2635 |
Approx( Approx const& other ) |
||
2636 |
: m_epsilon( other.m_epsilon ), |
||
2637 |
m_scale( other.m_scale ), |
||
2638 |
m_value( other.m_value ) |
||
2639 |
{} |
||
2640 |
|||
2641 |
static Approx custom() { |
||
2642 |
return Approx( 0 ); |
||
2643 |
} |
||
2644 |
|||
2645 |
Approx operator()( double value ) { |
||
2646 |
Approx approx( value ); |
||
2647 |
approx.epsilon( m_epsilon ); |
||
2648 |
approx.scale( m_scale ); |
||
2649 |
return approx; |
||
2650 |
} |
||
2651 |
|||
2652 |
friend bool operator == ( double lhs, Approx const& rhs ) { |
||
2653 |
// Thanks to Richard Harris for his help refining this formula |
||
2654 |
return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); |
||
2655 |
} |
||
2656 |
|||
2657 |
friend bool operator == ( Approx const& lhs, double rhs ) { |
||
2658 |
return operator==( rhs, lhs ); |
||
2659 |
} |
||
2660 |
|||
2661 |
friend bool operator != ( double lhs, Approx const& rhs ) { |
||
2662 |
return !operator==( lhs, rhs ); |
||
2663 |
} |
||
2664 |
|||
2665 |
friend bool operator != ( Approx const& lhs, double rhs ) { |
||
2666 |
return !operator==( rhs, lhs ); |
||
2667 |
} |
||
2668 |
|||
2669 |
Approx& epsilon( double newEpsilon ) { |
||
2670 |
m_epsilon = newEpsilon; |
||
2671 |
return *this; |
||
2672 |
} |
||
2673 |
|||
2674 |
Approx& scale( double newScale ) { |
||
2675 |
m_scale = newScale; |
||
2676 |
return *this; |
||
2677 |
} |
||
2678 |
|||
2679 |
std::string toString() const { |
||
2680 |
std::ostringstream oss; |
||
2681 |
oss << "Approx( " << Catch::toString( m_value ) << " )"; |
||
2682 |
return oss.str(); |
||
2683 |
} |
||
2684 |
|||
2685 |
private: |
||
2686 |
double m_epsilon; |
||
2687 |
double m_scale; |
||
2688 |
double m_value; |
||
2689 |
}; |
||
2690 |
} |
||
2691 |
|||
2692 |
template<> |
||
2693 |
inline std::string toString<Detail::Approx>( Detail::Approx const& value ) { |
||
2694 |
return value.toString(); |
||
2695 |
} |
||
2696 |
|||
2697 |
} // end namespace Catch |
||
2698 |
|||
2699 |
// #included from: internal/catch_interfaces_tag_alias_registry.h |
||
2700 |
#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED |
||
2701 |
|||
2702 |
// #included from: catch_tag_alias.h |
||
2703 |
#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED |
||
2704 |
|||
2705 |
#include <string> |
||
2706 |
|||
2707 |
namespace Catch { |
||
2708 |
|||
2709 |
struct TagAlias { |
||
2710 |
TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} |
||
2711 |
|||
2712 |
std::string tag; |
||
2713 |
SourceLineInfo lineInfo; |
||
2714 |
}; |
||
2715 |
|||
2716 |
struct RegistrarForTagAliases { |
||
2717 |
RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); |
||
2718 |
}; |
||
2719 |
|||
2720 |
} // end namespace Catch |
||
2721 |
|||
2722 |
#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } |
||
2723 |
// #included from: catch_option.hpp |
||
2724 |
#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED |
||
2725 |
|||
2726 |
namespace Catch { |
||
2727 |
|||
2728 |
// An optional type |
||
2729 |
template<typename T> |
||
2730 |
class Option { |
||
2731 |
public: |
||
2732 |
4 |
Option() : nullableValue( CATCH_NULL ) {} |
|
2733 |
Option( T const& _value ) |
||
2734 |
: nullableValue( new( storage ) T( _value ) ) |
||
2735 |
{} |
||
2736 |
Option( Option const& _other ) |
||
2737 |
: nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) |
||
2738 |
{} |
||
2739 |
|||
2740 |
~Option() { |
||
2741 |
4 |
reset(); |
|
2742 |
} |
||
2743 |
|||
2744 |
Option& operator= ( Option const& _other ) { |
||
2745 |
if( &_other != this ) { |
||
2746 |
reset(); |
||
2747 |
if( _other ) |
||
2748 |
nullableValue = new( storage ) T( *_other ); |
||
2749 |
} |
||
2750 |
return *this; |
||
2751 |
} |
||
2752 |
396 |
Option& operator = ( T const& _value ) { |
|
2753 |
396 |
reset(); |
|
2754 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗ |
398 |
nullableValue = new( storage ) T( _value ); |
2755 |
396 |
return *this; |
|
2756 |
} |
||
2757 |
|||
2758 |
void reset() { |
||
2759 |
✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✓✗✓✗ ✗✗✗✗ ✗✓✗✓ ✓✗✗✗ ✗✗✗✗ ✗✗ |
797 |
if( nullableValue ) |
2760 |
396 |
nullableValue->~T(); |
|
2761 |
794 |
nullableValue = CATCH_NULL; |
|
2762 |
} |
||
2763 |
|||
2764 |
T& operator*() { return *nullableValue; } |
||
2765 |
T const& operator*() const { return *nullableValue; } |
||
2766 |
T* operator->() { return nullableValue; } |
||
2767 |
const T* operator->() const { return nullableValue; } |
||
2768 |
|||
2769 |
T valueOr( T const& defaultValue ) const { |
||
2770 |
return nullableValue ? *nullableValue : defaultValue; |
||
2771 |
} |
||
2772 |
|||
2773 |
bool some() const { return nullableValue != CATCH_NULL; } |
||
2774 |
bool none() const { return nullableValue == CATCH_NULL; } |
||
2775 |
|||
2776 |
bool operator !() const { return nullableValue == CATCH_NULL; } |
||
2777 |
operator SafeBool::type() const { |
||
2778 |
2 |
return SafeBool::makeSafe( some() ); |
|
2779 |
} |
||
2780 |
|||
2781 |
private: |
||
2782 |
T* nullableValue; |
||
2783 |
char storage[sizeof(T)]; |
||
2784 |
}; |
||
2785 |
|||
2786 |
} // end namespace Catch |
||
2787 |
|||
2788 |
namespace Catch { |
||
2789 |
|||
2790 |
struct ITagAliasRegistry { |
||
2791 |
virtual ~ITagAliasRegistry(); |
||
2792 |
virtual Option<TagAlias> find( std::string const& alias ) const = 0; |
||
2793 |
virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; |
||
2794 |
|||
2795 |
static ITagAliasRegistry const& get(); |
||
2796 |
}; |
||
2797 |
|||
2798 |
} // end namespace Catch |
||
2799 |
|||
2800 |
// These files are included here so the single_include script doesn't put them |
||
2801 |
// in the conditionally compiled sections |
||
2802 |
// #included from: internal/catch_test_case_info.h |
||
2803 |
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED |
||
2804 |
|||
2805 |
#include <string> |
||
2806 |
#include <set> |
||
2807 |
|||
2808 |
#ifdef __clang__ |
||
2809 |
#pragma clang diagnostic push |
||
2810 |
#pragma clang diagnostic ignored "-Wpadded" |
||
2811 |
#endif |
||
2812 |
|||
2813 |
namespace Catch { |
||
2814 |
|||
2815 |
struct ITestCase; |
||
2816 |
|||
2817 |
29304 |
struct TestCaseInfo { |
|
2818 |
enum SpecialProperties{ |
||
2819 |
None = 0, |
||
2820 |
IsHidden = 1 << 1, |
||
2821 |
ShouldFail = 1 << 2, |
||
2822 |
MayFail = 1 << 3, |
||
2823 |
Throws = 1 << 4 |
||
2824 |
}; |
||
2825 |
|||
2826 |
TestCaseInfo( std::string const& _name, |
||
2827 |
std::string const& _className, |
||
2828 |
std::string const& _description, |
||
2829 |
std::set<std::string> const& _tags, |
||
2830 |
SourceLineInfo const& _lineInfo ); |
||
2831 |
|||
2832 |
TestCaseInfo( TestCaseInfo const& other ); |
||
2833 |
|||
2834 |
friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags ); |
||
2835 |
|||
2836 |
bool isHidden() const; |
||
2837 |
bool throws() const; |
||
2838 |
bool okToFail() const; |
||
2839 |
bool expectedToFail() const; |
||
2840 |
|||
2841 |
std::string name; |
||
2842 |
std::string className; |
||
2843 |
std::string description; |
||
2844 |
std::set<std::string> tags; |
||
2845 |
std::set<std::string> lcaseTags; |
||
2846 |
std::string tagsAsString; |
||
2847 |
SourceLineInfo lineInfo; |
||
2848 |
SpecialProperties properties; |
||
2849 |
}; |
||
2850 |
|||
2851 |
4174 |
class TestCase : public TestCaseInfo { |
|
2852 |
public: |
||
2853 |
|||
2854 |
TestCase( ITestCase* testCase, TestCaseInfo const& info ); |
||
2855 |
TestCase( TestCase const& other ); |
||
2856 |
|||
2857 |
TestCase withName( std::string const& _newName ) const; |
||
2858 |
|||
2859 |
void invoke() const; |
||
2860 |
|||
2861 |
TestCaseInfo const& getTestCaseInfo() const; |
||
2862 |
|||
2863 |
void swap( TestCase& other ); |
||
2864 |
bool operator == ( TestCase const& other ) const; |
||
2865 |
bool operator < ( TestCase const& other ) const; |
||
2866 |
TestCase& operator = ( TestCase const& other ); |
||
2867 |
|||
2868 |
private: |
||
2869 |
Ptr<ITestCase> test; |
||
2870 |
}; |
||
2871 |
|||
2872 |
TestCase makeTestCase( ITestCase* testCase, |
||
2873 |
std::string const& className, |
||
2874 |
std::string const& name, |
||
2875 |
std::string const& description, |
||
2876 |
SourceLineInfo const& lineInfo ); |
||
2877 |
} |
||
2878 |
|||
2879 |
#ifdef __clang__ |
||
2880 |
#pragma clang diagnostic pop |
||
2881 |
#endif |
||
2882 |
|||
2883 |
|||
2884 |
#ifdef __OBJC__ |
||
2885 |
// #included from: internal/catch_objc.hpp |
||
2886 |
#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED |
||
2887 |
|||
2888 |
#import <objc/runtime.h> |
||
2889 |
|||
2890 |
#include <string> |
||
2891 |
|||
2892 |
// NB. Any general catch headers included here must be included |
||
2893 |
// in catch.hpp first to make sure they are included by the single |
||
2894 |
// header for non obj-usage |
||
2895 |
|||
2896 |
/////////////////////////////////////////////////////////////////////////////// |
||
2897 |
// This protocol is really only here for (self) documenting purposes, since |
||
2898 |
// all its methods are optional. |
||
2899 |
@protocol OcFixture |
||
2900 |
|||
2901 |
@optional |
||
2902 |
|||
2903 |
-(void) setUp; |
||
2904 |
-(void) tearDown; |
||
2905 |
|||
2906 |
@end |
||
2907 |
|||
2908 |
namespace Catch { |
||
2909 |
|||
2910 |
class OcMethod : public SharedImpl<ITestCase> { |
||
2911 |
|||
2912 |
public: |
||
2913 |
OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} |
||
2914 |
|||
2915 |
virtual void invoke() const { |
||
2916 |
id obj = [[m_cls alloc] init]; |
||
2917 |
|||
2918 |
performOptionalSelector( obj, @selector(setUp) ); |
||
2919 |
performOptionalSelector( obj, m_sel ); |
||
2920 |
performOptionalSelector( obj, @selector(tearDown) ); |
||
2921 |
|||
2922 |
arcSafeRelease( obj ); |
||
2923 |
} |
||
2924 |
private: |
||
2925 |
virtual ~OcMethod() {} |
||
2926 |
|||
2927 |
Class m_cls; |
||
2928 |
SEL m_sel; |
||
2929 |
}; |
||
2930 |
|||
2931 |
namespace Detail{ |
||
2932 |
|||
2933 |
inline std::string getAnnotation( Class cls, |
||
2934 |
std::string const& annotationName, |
||
2935 |
std::string const& testCaseName ) { |
||
2936 |
NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; |
||
2937 |
SEL sel = NSSelectorFromString( selStr ); |
||
2938 |
arcSafeRelease( selStr ); |
||
2939 |
id value = performOptionalSelector( cls, sel ); |
||
2940 |
if( value ) |
||
2941 |
return [(NSString*)value UTF8String]; |
||
2942 |
return ""; |
||
2943 |
} |
||
2944 |
} |
||
2945 |
|||
2946 |
inline size_t registerTestMethods() { |
||
2947 |
size_t noTestMethods = 0; |
||
2948 |
int noClasses = objc_getClassList( CATCH_NULL, 0 ); |
||
2949 |
|||
2950 |
Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); |
||
2951 |
objc_getClassList( classes, noClasses ); |
||
2952 |
|||
2953 |
for( int c = 0; c < noClasses; c++ ) { |
||
2954 |
Class cls = classes[c]; |
||
2955 |
{ |
||
2956 |
u_int count; |
||
2957 |
Method* methods = class_copyMethodList( cls, &count ); |
||
2958 |
for( u_int m = 0; m < count ; m++ ) { |
||
2959 |
SEL selector = method_getName(methods[m]); |
||
2960 |
std::string methodName = sel_getName(selector); |
||
2961 |
if( startsWith( methodName, "Catch_TestCase_" ) ) { |
||
2962 |
std::string testCaseName = methodName.substr( 15 ); |
||
2963 |
std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); |
||
2964 |
std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); |
||
2965 |
const char* className = class_getName( cls ); |
||
2966 |
|||
2967 |
getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); |
||
2968 |
noTestMethods++; |
||
2969 |
} |
||
2970 |
} |
||
2971 |
free(methods); |
||
2972 |
} |
||
2973 |
} |
||
2974 |
return noTestMethods; |
||
2975 |
} |
||
2976 |
|||
2977 |
namespace Matchers { |
||
2978 |
namespace Impl { |
||
2979 |
namespace NSStringMatchers { |
||
2980 |
|||
2981 |
template<typename MatcherT> |
||
2982 |
struct StringHolder : MatcherImpl<MatcherT, NSString*>{ |
||
2983 |
StringHolder( NSString* substr ) : m_substr( [substr copy] ){} |
||
2984 |
StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} |
||
2985 |
StringHolder() { |
||
2986 |
arcSafeRelease( m_substr ); |
||
2987 |
} |
||
2988 |
|||
2989 |
NSString* m_substr; |
||
2990 |
}; |
||
2991 |
|||
2992 |
struct Equals : StringHolder<Equals> { |
||
2993 |
Equals( NSString* substr ) : StringHolder( substr ){} |
||
2994 |
|||
2995 |
virtual bool match( ExpressionType const& str ) const { |
||
2996 |
return (str != nil || m_substr == nil ) && |
||
2997 |
[str isEqualToString:m_substr]; |
||
2998 |
} |
||
2999 |
|||
3000 |
virtual std::string toString() const { |
||
3001 |
return "equals string: " + Catch::toString( m_substr ); |
||
3002 |
} |
||
3003 |
}; |
||
3004 |
|||
3005 |
struct Contains : StringHolder<Contains> { |
||
3006 |
Contains( NSString* substr ) : StringHolder( substr ){} |
||
3007 |
|||
3008 |
virtual bool match( ExpressionType const& str ) const { |
||
3009 |
return (str != nil || m_substr == nil ) && |
||
3010 |
[str rangeOfString:m_substr].location != NSNotFound; |
||
3011 |
} |
||
3012 |
|||
3013 |
virtual std::string toString() const { |
||
3014 |
return "contains string: " + Catch::toString( m_substr ); |
||
3015 |
} |
||
3016 |
}; |
||
3017 |
|||
3018 |
struct StartsWith : StringHolder<StartsWith> { |
||
3019 |
StartsWith( NSString* substr ) : StringHolder( substr ){} |
||
3020 |
|||
3021 |
virtual bool match( ExpressionType const& str ) const { |
||
3022 |
return (str != nil || m_substr == nil ) && |
||
3023 |
[str rangeOfString:m_substr].location == 0; |
||
3024 |
} |
||
3025 |
|||
3026 |
virtual std::string toString() const { |
||
3027 |
return "starts with: " + Catch::toString( m_substr ); |
||
3028 |
} |
||
3029 |
}; |
||
3030 |
struct EndsWith : StringHolder<EndsWith> { |
||
3031 |
EndsWith( NSString* substr ) : StringHolder( substr ){} |
||
3032 |
|||
3033 |
virtual bool match( ExpressionType const& str ) const { |
||
3034 |
return (str != nil || m_substr == nil ) && |
||
3035 |
[str rangeOfString:m_substr].location == [str length] - [m_substr length]; |
||
3036 |
} |
||
3037 |
|||
3038 |
virtual std::string toString() const { |
||
3039 |
return "ends with: " + Catch::toString( m_substr ); |
||
3040 |
} |
||
3041 |
}; |
||
3042 |
|||
3043 |
} // namespace NSStringMatchers |
||
3044 |
} // namespace Impl |
||
3045 |
|||
3046 |
inline Impl::NSStringMatchers::Equals |
||
3047 |
Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } |
||
3048 |
|||
3049 |
inline Impl::NSStringMatchers::Contains |
||
3050 |
Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } |
||
3051 |
|||
3052 |
inline Impl::NSStringMatchers::StartsWith |
||
3053 |
StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } |
||
3054 |
|||
3055 |
inline Impl::NSStringMatchers::EndsWith |
||
3056 |
EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } |
||
3057 |
|||
3058 |
} // namespace Matchers |
||
3059 |
|||
3060 |
using namespace Matchers; |
||
3061 |
|||
3062 |
} // namespace Catch |
||
3063 |
|||
3064 |
/////////////////////////////////////////////////////////////////////////////// |
||
3065 |
#define OC_TEST_CASE( name, desc )\ |
||
3066 |
+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ |
||
3067 |
{\ |
||
3068 |
return @ name; \ |
||
3069 |
}\ |
||
3070 |
+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ |
||
3071 |
{ \ |
||
3072 |
return @ desc; \ |
||
3073 |
} \ |
||
3074 |
-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) |
||
3075 |
|||
3076 |
#endif |
||
3077 |
|||
3078 |
#ifdef CATCH_IMPL |
||
3079 |
// #included from: internal/catch_impl.hpp |
||
3080 |
#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED |
||
3081 |
|||
3082 |
// Collect all the implementation files together here |
||
3083 |
// These are the equivalent of what would usually be cpp files |
||
3084 |
|||
3085 |
#ifdef __clang__ |
||
3086 |
#pragma clang diagnostic push |
||
3087 |
#pragma clang diagnostic ignored "-Wweak-vtables" |
||
3088 |
#endif |
||
3089 |
|||
3090 |
// #included from: ../catch_session.hpp |
||
3091 |
#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED |
||
3092 |
|||
3093 |
// #included from: internal/catch_commandline.hpp |
||
3094 |
#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED |
||
3095 |
|||
3096 |
// #included from: catch_config.hpp |
||
3097 |
#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED |
||
3098 |
|||
3099 |
// #included from: catch_test_spec_parser.hpp |
||
3100 |
#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED |
||
3101 |
|||
3102 |
#ifdef __clang__ |
||
3103 |
#pragma clang diagnostic push |
||
3104 |
#pragma clang diagnostic ignored "-Wpadded" |
||
3105 |
#endif |
||
3106 |
|||
3107 |
// #included from: catch_test_spec.hpp |
||
3108 |
#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED |
||
3109 |
|||
3110 |
#ifdef __clang__ |
||
3111 |
#pragma clang diagnostic push |
||
3112 |
#pragma clang diagnostic ignored "-Wpadded" |
||
3113 |
#endif |
||
3114 |
|||
3115 |
// #included from: catch_wildcard_pattern.hpp |
||
3116 |
#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED |
||
3117 |
|||
3118 |
namespace Catch |
||
3119 |
{ |
||
3120 |
class WildcardPattern { |
||
3121 |
enum WildcardPosition { |
||
3122 |
NoWildcard = 0, |
||
3123 |
WildcardAtStart = 1, |
||
3124 |
WildcardAtEnd = 2, |
||
3125 |
WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd |
||
3126 |
}; |
||
3127 |
|||
3128 |
public: |
||
3129 |
|||
3130 |
WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) |
||
3131 |
: m_caseSensitivity( caseSensitivity ), |
||
3132 |
m_wildcard( NoWildcard ), |
||
3133 |
m_pattern( adjustCase( pattern ) ) |
||
3134 |
{ |
||
3135 |
if( startsWith( m_pattern, "*" ) ) { |
||
3136 |
m_pattern = m_pattern.substr( 1 ); |
||
3137 |
m_wildcard = WildcardAtStart; |
||
3138 |
} |
||
3139 |
if( endsWith( m_pattern, "*" ) ) { |
||
3140 |
m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); |
||
3141 |
m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd ); |
||
3142 |
} |
||
3143 |
} |
||
3144 |
virtual ~WildcardPattern(); |
||
3145 |
virtual bool matches( std::string const& str ) const { |
||
3146 |
switch( m_wildcard ) { |
||
3147 |
case NoWildcard: |
||
3148 |
return m_pattern == adjustCase( str ); |
||
3149 |
case WildcardAtStart: |
||
3150 |
return endsWith( adjustCase( str ), m_pattern ); |
||
3151 |
case WildcardAtEnd: |
||
3152 |
return startsWith( adjustCase( str ), m_pattern ); |
||
3153 |
case WildcardAtBothEnds: |
||
3154 |
return contains( adjustCase( str ), m_pattern ); |
||
3155 |
} |
||
3156 |
|||
3157 |
#ifdef __clang__ |
||
3158 |
#pragma clang diagnostic push |
||
3159 |
#pragma clang diagnostic ignored "-Wunreachable-code" |
||
3160 |
#endif |
||
3161 |
throw std::logic_error( "Unknown enum" ); |
||
3162 |
#ifdef __clang__ |
||
3163 |
#pragma clang diagnostic pop |
||
3164 |
#endif |
||
3165 |
} |
||
3166 |
private: |
||
3167 |
std::string adjustCase( std::string const& str ) const { |
||
3168 |
return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; |
||
3169 |
} |
||
3170 |
CaseSensitive::Choice m_caseSensitivity; |
||
3171 |
WildcardPosition m_wildcard; |
||
3172 |
std::string m_pattern; |
||
3173 |
}; |
||
3174 |
} |
||
3175 |
|||
3176 |
#include <string> |
||
3177 |
#include <vector> |
||
3178 |
|||
3179 |
namespace Catch { |
||
3180 |
|||
3181 |
✗✓✗✓ ✗✗✗✗ ✗✗✗✗ |
12 |
class TestSpec { |
3182 |
4 |
struct Pattern : SharedImpl<> { |
|
3183 |
virtual ~Pattern(); |
||
3184 |
virtual bool matches( TestCaseInfo const& testCase ) const = 0; |
||
3185 |
}; |
||
3186 |
class NamePattern : public Pattern { |
||
3187 |
public: |
||
3188 |
NamePattern( std::string const& name ) |
||
3189 |
: m_wildcardPattern( toLower( name ), CaseSensitive::No ) |
||
3190 |
{} |
||
3191 |
virtual ~NamePattern(); |
||
3192 |
virtual bool matches( TestCaseInfo const& testCase ) const { |
||
3193 |
return m_wildcardPattern.matches( toLower( testCase.name ) ); |
||
3194 |
} |
||
3195 |
private: |
||
3196 |
WildcardPattern m_wildcardPattern; |
||
3197 |
}; |
||
3198 |
|||
3199 |
class TagPattern : public Pattern { |
||
3200 |
public: |
||
3201 |
3 |
TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} |
|
3202 |
virtual ~TagPattern(); |
||
3203 |
394 |
virtual bool matches( TestCaseInfo const& testCase ) const { |
|
3204 |
1576 |
return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); |
|
3205 |
} |
||
3206 |
private: |
||
3207 |
std::string m_tag; |
||
3208 |
}; |
||
3209 |
|||
3210 |
class ExcludedPattern : public Pattern { |
||
3211 |
public: |
||
3212 |
3 |
ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} |
|
3213 |
virtual ~ExcludedPattern(); |
||
3214 |
788 |
virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } |
|
3215 |
private: |
||
3216 |
Ptr<Pattern> m_underlyingPattern; |
||
3217 |
}; |
||
3218 |
|||
3219 |
✓✗✓✗ |
12 |
struct Filter { |
3220 |
std::vector<Ptr<Pattern> > m_patterns; |
||
3221 |
|||
3222 |
bool matches( TestCaseInfo const& testCase ) const { |
||
3223 |
// All patterns in a filter must match for the filter to be a match |
||
3224 |
✓✓ | 1970 |
for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) |
3225 |
✓✗ | 788 |
if( !(*it)->matches( testCase ) ) |
3226 |
return false; |
||
3227 |
return true; |
||
3228 |
} |
||
3229 |
}; |
||
3230 |
|||
3231 |
public: |
||
3232 |
bool hasFilters() const { |
||
3233 |
2 |
return !m_filters.empty(); |
|
3234 |
} |
||
3235 |
394 |
bool matches( TestCaseInfo const& testCase ) const { |
|
3236 |
// A TestSpec matches if any filter matches |
||
3237 |
✓✗ | 1576 |
for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) |
3238 |
✗✓ | 788 |
if( it->matches( testCase ) ) |
3239 |
return true; |
||
3240 |
return false; |
||
3241 |
} |
||
3242 |
|||
3243 |
private: |
||
3244 |
std::vector<Filter> m_filters; |
||
3245 |
|||
3246 |
friend class TestSpecParser; |
||
3247 |
}; |
||
3248 |
} |
||
3249 |
|||
3250 |
#ifdef __clang__ |
||
3251 |
#pragma clang diagnostic pop |
||
3252 |
#endif |
||
3253 |
|||
3254 |
namespace Catch { |
||
3255 |
|||
3256 |
4 |
class TestSpecParser { |
|
3257 |
enum Mode{ None, Name, QuotedName, Tag }; |
||
3258 |
Mode m_mode; |
||
3259 |
bool m_exclusion; |
||
3260 |
std::size_t m_start, m_pos; |
||
3261 |
std::string m_arg; |
||
3262 |
TestSpec::Filter m_currentFilter; |
||
3263 |
TestSpec m_testSpec; |
||
3264 |
ITagAliasRegistry const* m_tagAliases; |
||
3265 |
|||
3266 |
public: |
||
3267 |
4 |
TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} |
|
3268 |
|||
3269 |
1 |
TestSpecParser& parse( std::string const& arg ) { |
|
3270 |
1 |
m_mode = None; |
|
3271 |
1 |
m_exclusion = false; |
|
3272 |
1 |
m_start = std::string::npos; |
|
3273 |
2 |
m_arg = m_tagAliases->expandAliases( arg ); |
|
3274 |
✓✓ | 4 |
for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) |
3275 |
6 |
visitChar( m_arg[m_pos] ); |
|
3276 |
✗✓ | 1 |
if( m_mode == Name ) |
3277 |
addPattern<TestSpec::NamePattern>(); |
||
3278 |
1 |
return *this; |
|
3279 |
} |
||
3280 |
TestSpec testSpec() { |
||
3281 |
✓✗✗✗ ✗✗✗✗ ✗✗ |
1 |
addFilter(); |
3282 |
2 |
return m_testSpec; |
|
3283 |
} |
||
3284 |
private: |
||
3285 |
3 |
void visitChar( char c ) { |
|
3286 |
✓✓ | 3 |
if( m_mode == None ) { |
3287 |
✓✓✗✗ ✗ |
2 |
switch( c ) { |
3288 |
case ' ': return; |
||
3289 |
1 |
case '~': m_exclusion = true; return; |
|
3290 |
1 |
case '[': return startNewMode( Tag, ++m_pos ); |
|
3291 |
case '"': return startNewMode( QuotedName, ++m_pos ); |
||
3292 |
default: startNewMode( Name, m_pos ); break; |
||
3293 |
} |
||
3294 |
} |
||
3295 |
✗✓ | 1 |
if( m_mode == Name ) { |
3296 |
if( c == ',' ) { |
||
3297 |
addPattern<TestSpec::NamePattern>(); |
||
3298 |
addFilter(); |
||
3299 |
} |
||
3300 |
else if( c == '[' ) { |
||
3301 |
if( subString() == "exclude:" ) |
||
3302 |
m_exclusion = true; |
||
3303 |
else |
||
3304 |
addPattern<TestSpec::NamePattern>(); |
||
3305 |
startNewMode( Tag, ++m_pos ); |
||
3306 |
} |
||
3307 |
} |
||
3308 |
✗✓✗✗ |
1 |
else if( m_mode == QuotedName && c == '"' ) |
3309 |
addPattern<TestSpec::NamePattern>(); |
||
3310 |
✓✗✓✗ |
1 |
else if( m_mode == Tag && c == ']' ) |
3311 |
1 |
addPattern<TestSpec::TagPattern>(); |
|
3312 |
} |
||
3313 |
void startNewMode( Mode mode, std::size_t start ) { |
||
3314 |
1 |
m_mode = mode; |
|
3315 |
1 |
m_start = start; |
|
3316 |
} |
||
3317 |
1 |
std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } |
|
3318 |
template<typename T> |
||
3319 |
1 |
void addPattern() { |
|
3320 |
2 |
std::string token = subString(); |
|
3321 |
✓✗✓✗ ✗✓✗✗ ✗✗✗✗ |
4 |
if( startsWith( token, "exclude:" ) ) { |
3322 |
m_exclusion = true; |
||
3323 |
token = token.substr( 8 ); |
||
3324 |
} |
||
3325 |
✓✗✗✗ |
1 |
if( !token.empty() ) { |
3326 |
✓✗✓✗ ✗✗✗✗ |
3 |
Ptr<TestSpec::Pattern> pattern = new T( token ); |
3327 |
✓✗✗✗ |
1 |
if( m_exclusion ) |
3328 |
✓✗✗✗ |
2 |
pattern = new TestSpec::ExcludedPattern( pattern ); |
3329 |
✓✗✗✗ |
1 |
m_currentFilter.m_patterns.push_back( pattern ); |
3330 |
} |
||
3331 |
1 |
m_exclusion = false; |
|
3332 |
1 |
m_mode = None; |
|
3333 |
1 |
} |
|
3334 |
1 |
void addFilter() { |
|
3335 |
✓✗ | 2 |
if( !m_currentFilter.m_patterns.empty() ) { |
3336 |
1 |
m_testSpec.m_filters.push_back( m_currentFilter ); |
|
3337 |
4 |
m_currentFilter = TestSpec::Filter(); |
|
3338 |
} |
||
3339 |
1 |
} |
|
3340 |
}; |
||
3341 |
inline TestSpec parseTestSpec( std::string const& arg ) { |
||
3342 |
return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); |
||
3343 |
} |
||
3344 |
|||
3345 |
} // namespace Catch |
||
3346 |
|||
3347 |
#ifdef __clang__ |
||
3348 |
#pragma clang diagnostic pop |
||
3349 |
#endif |
||
3350 |
|||
3351 |
// #included from: catch_interfaces_config.h |
||
3352 |
#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED |
||
3353 |
|||
3354 |
#include <iostream> |
||
3355 |
#include <string> |
||
3356 |
#include <vector> |
||
3357 |
|||
3358 |
namespace Catch { |
||
3359 |
|||
3360 |
struct Verbosity { enum Level { |
||
3361 |
NoOutput = 0, |
||
3362 |
Quiet, |
||
3363 |
Normal |
||
3364 |
}; }; |
||
3365 |
|||
3366 |
struct WarnAbout { enum What { |
||
3367 |
Nothing = 0x00, |
||
3368 |
NoAssertions = 0x01 |
||
3369 |
}; }; |
||
3370 |
|||
3371 |
struct ShowDurations { enum OrNot { |
||
3372 |
DefaultForReporter, |
||
3373 |
Always, |
||
3374 |
Never |
||
3375 |
}; }; |
||
3376 |
struct RunTests { enum InWhatOrder { |
||
3377 |
InDeclarationOrder, |
||
3378 |
InLexicographicalOrder, |
||
3379 |
InRandomOrder |
||
3380 |
}; }; |
||
3381 |
struct UseColour { enum YesOrNo { |
||
3382 |
Auto, |
||
3383 |
Yes, |
||
3384 |
No |
||
3385 |
}; }; |
||
3386 |
|||
3387 |
class TestSpec; |
||
3388 |
|||
3389 |
2 |
struct IConfig : IShared { |
|
3390 |
|||
3391 |
virtual ~IConfig(); |
||
3392 |
|||
3393 |
virtual bool allowThrows() const = 0; |
||
3394 |
virtual std::ostream& stream() const = 0; |
||
3395 |
virtual std::string name() const = 0; |
||
3396 |
virtual bool includeSuccessfulResults() const = 0; |
||
3397 |
virtual bool shouldDebugBreak() const = 0; |
||
3398 |
virtual bool warnAboutMissingAssertions() const = 0; |
||
3399 |
virtual int abortAfter() const = 0; |
||
3400 |
virtual bool showInvisibles() const = 0; |
||
3401 |
virtual ShowDurations::OrNot showDurations() const = 0; |
||
3402 |
virtual TestSpec const& testSpec() const = 0; |
||
3403 |
virtual RunTests::InWhatOrder runOrder() const = 0; |
||
3404 |
virtual unsigned int rngSeed() const = 0; |
||
3405 |
virtual UseColour::YesOrNo useColour() const = 0; |
||
3406 |
}; |
||
3407 |
} |
||
3408 |
|||
3409 |
// #included from: catch_stream.h |
||
3410 |
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED |
||
3411 |
|||
3412 |
// #included from: catch_streambuf.h |
||
3413 |
#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED |
||
3414 |
|||
3415 |
#include <streambuf> |
||
3416 |
|||
3417 |
namespace Catch { |
||
3418 |
|||
3419 |
class StreamBufBase : public std::streambuf { |
||
3420 |
public: |
||
3421 |
virtual ~StreamBufBase() CATCH_NOEXCEPT; |
||
3422 |
}; |
||
3423 |
} |
||
3424 |
|||
3425 |
#include <streambuf> |
||
3426 |
#include <ostream> |
||
3427 |
#include <fstream> |
||
3428 |
|||
3429 |
namespace Catch { |
||
3430 |
|||
3431 |
std::ostream& cout(); |
||
3432 |
std::ostream& cerr(); |
||
3433 |
|||
3434 |
struct IStream { |
||
3435 |
virtual ~IStream() CATCH_NOEXCEPT; |
||
3436 |
virtual std::ostream& stream() const = 0; |
||
3437 |
}; |
||
3438 |
|||
3439 |
class FileStream : public IStream { |
||
3440 |
mutable std::ofstream m_ofs; |
||
3441 |
public: |
||
3442 |
FileStream( std::string const& filename ); |
||
3443 |
virtual ~FileStream() CATCH_NOEXCEPT; |
||
3444 |
public: // IStream |
||
3445 |
virtual std::ostream& stream() const CATCH_OVERRIDE; |
||
3446 |
}; |
||
3447 |
|||
3448 |
class CoutStream : public IStream { |
||
3449 |
mutable std::ostream m_os; |
||
3450 |
public: |
||
3451 |
CoutStream(); |
||
3452 |
virtual ~CoutStream() CATCH_NOEXCEPT; |
||
3453 |
|||
3454 |
public: // IStream |
||
3455 |
virtual std::ostream& stream() const CATCH_OVERRIDE; |
||
3456 |
}; |
||
3457 |
|||
3458 |
class DebugOutStream : public IStream { |
||
3459 |
std::auto_ptr<StreamBufBase> m_streamBuf; |
||
3460 |
mutable std::ostream m_os; |
||
3461 |
public: |
||
3462 |
DebugOutStream(); |
||
3463 |
virtual ~DebugOutStream() CATCH_NOEXCEPT; |
||
3464 |
|||
3465 |
public: // IStream |
||
3466 |
virtual std::ostream& stream() const CATCH_OVERRIDE; |
||
3467 |
}; |
||
3468 |
} |
||
3469 |
|||
3470 |
#include <memory> |
||
3471 |
#include <vector> |
||
3472 |
#include <string> |
||
3473 |
#include <iostream> |
||
3474 |
#include <ctime> |
||
3475 |
|||
3476 |
#ifndef CATCH_CONFIG_CONSOLE_WIDTH |
||
3477 |
#define CATCH_CONFIG_CONSOLE_WIDTH 80 |
||
3478 |
#endif |
||
3479 |
|||
3480 |
namespace Catch { |
||
3481 |
|||
3482 |
✓✗✓✗ |
12 |
struct ConfigData { |
3483 |
|||
3484 |
ConfigData() |
||
3485 |
1 |
: listTests( false ), |
|
3486 |
listTags( false ), |
||
3487 |
listReporters( false ), |
||
3488 |
listTestNamesOnly( false ), |
||
3489 |
showSuccessfulTests( false ), |
||
3490 |
shouldDebugBreak( false ), |
||
3491 |
noThrow( false ), |
||
3492 |
showHelp( false ), |
||
3493 |
showInvisibles( false ), |
||
3494 |
filenamesAsTags( false ), |
||
3495 |
abortAfter( -1 ), |
||
3496 |
rngSeed( 0 ), |
||
3497 |
verbosity( Verbosity::Normal ), |
||
3498 |
warnings( WarnAbout::Nothing ), |
||
3499 |
showDurations( ShowDurations::DefaultForReporter ), |
||
3500 |
runOrder( RunTests::InDeclarationOrder ), |
||
3501 |
6 |
useColour( UseColour::Auto ) |
|
3502 |
{} |
||
3503 |
|||
3504 |
bool listTests; |
||
3505 |
bool listTags; |
||
3506 |
bool listReporters; |
||
3507 |
bool listTestNamesOnly; |
||
3508 |
|||
3509 |
bool showSuccessfulTests; |
||
3510 |
bool shouldDebugBreak; |
||
3511 |
bool noThrow; |
||
3512 |
bool showHelp; |
||
3513 |
bool showInvisibles; |
||
3514 |
bool filenamesAsTags; |
||
3515 |
|||
3516 |
int abortAfter; |
||
3517 |
unsigned int rngSeed; |
||
3518 |
|||
3519 |
Verbosity::Level verbosity; |
||
3520 |
WarnAbout::What warnings; |
||
3521 |
ShowDurations::OrNot showDurations; |
||
3522 |
RunTests::InWhatOrder runOrder; |
||
3523 |
UseColour::YesOrNo useColour; |
||
3524 |
|||
3525 |
std::string outputFilename; |
||
3526 |
std::string name; |
||
3527 |
std::string processName; |
||
3528 |
|||
3529 |
std::vector<std::string> reporterNames; |
||
3530 |
std::vector<std::string> testsOrTags; |
||
3531 |
}; |
||
3532 |
|||
3533 |
class Config : public SharedImpl<IConfig> { |
||
3534 |
private: |
||
3535 |
Config( Config const& other ); |
||
3536 |
Config& operator = ( Config const& other ); |
||
3537 |
virtual void dummy(); |
||
3538 |
public: |
||
3539 |
|||
3540 |
Config() |
||
3541 |
{} |
||
3542 |
|||
3543 |
1 |
Config( ConfigData const& data ) |
|
3544 |
1 |
: m_data( data ), |
|
3545 |
✓✗ | 4 |
m_stream( openStream() ) |
3546 |
{ |
||
3547 |
✗✓ | 2 |
if( !data.testsOrTags.empty() ) { |
3548 |
TestSpecParser parser( ITagAliasRegistry::get() ); |
||
3549 |
for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) |
||
3550 |
parser.parse( data.testsOrTags[i] ); |
||
3551 |
m_testSpec = parser.testSpec(); |
||
3552 |
} |
||
3553 |
1 |
} |
|
3554 |
|||
3555 |
5 |
virtual ~Config() { |
|
3556 |
2 |
} |
|
3557 |
|||
3558 |
std::string const& getFilename() const { |
||
3559 |
return m_data.outputFilename ; |
||
3560 |
} |
||
3561 |
|||
3562 |
bool listTests() const { return m_data.listTests; } |
||
3563 |
bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } |
||
3564 |
bool listTags() const { return m_data.listTags; } |
||
3565 |
bool listReporters() const { return m_data.listReporters; } |
||
3566 |
|||
3567 |
std::string getProcessName() const { return m_data.processName; } |
||
3568 |
|||
3569 |
bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } |
||
3570 |
|||
3571 |
1 |
std::vector<std::string> getReporterNames() const { return m_data.reporterNames; } |
|
3572 |
|||
3573 |
1141 |
int abortAfter() const { return m_data.abortAfter; } |
|
3574 |
|||
3575 |
1 |
TestSpec const& testSpec() const { return m_testSpec; } |
|
3576 |
|||
3577 |
bool showHelp() const { return m_data.showHelp; } |
||
3578 |
164047 |
bool showInvisibles() const { return m_data.showInvisibles; } |
|
3579 |
|||
3580 |
// IConfig interface |
||
3581 |
425 |
virtual bool allowThrows() const { return !m_data.noThrow; } |
|
3582 |
2 |
virtual std::ostream& stream() const { return m_stream->stream(); } |
|
3583 |
✓✗ | 9 |
virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } |
3584 |
1432923 |
virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } |
|
3585 |
148 |
virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } |
|
3586 |
1145 |
virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } |
|
3587 |
3 |
virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } |
|
3588 |
746 |
virtual unsigned int rngSeed() const { return m_data.rngSeed; } |
|
3589 |
1 |
virtual UseColour::YesOrNo useColour() const { return m_data.useColour; } |
|
3590 |
|||
3591 |
private: |
||
3592 |
|||
3593 |
1 |
IStream const* openStream() { |
|
3594 |
✓✗ | 2 |
if( m_data.outputFilename.empty() ) |
3595 |
1 |
return new CoutStream(); |
|
3596 |
else if( m_data.outputFilename[0] == '%' ) { |
||
3597 |
if( m_data.outputFilename == "%debug" ) |
||
3598 |
return new DebugOutStream(); |
||
3599 |
else |
||
3600 |
throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); |
||
3601 |
} |
||
3602 |
else |
||
3603 |
return new FileStream( m_data.outputFilename ); |
||
3604 |
} |
||
3605 |
ConfigData m_data; |
||
3606 |
|||
3607 |
std::auto_ptr<IStream const> m_stream; |
||
3608 |
TestSpec m_testSpec; |
||
3609 |
}; |
||
3610 |
|||
3611 |
} // end namespace Catch |
||
3612 |
|||
3613 |
// #included from: catch_clara.h |
||
3614 |
#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED |
||
3615 |
|||
3616 |
// Use Catch's value for console width (store Clara's off to the side, if present) |
||
3617 |
#ifdef CLARA_CONFIG_CONSOLE_WIDTH |
||
3618 |
#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH |
||
3619 |
#undef CLARA_CONFIG_CONSOLE_WIDTH |
||
3620 |
#endif |
||
3621 |
#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH |
||
3622 |
|||
3623 |
// Declare Clara inside the Catch namespace |
||
3624 |
#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { |
||
3625 |
// #included from: ../external/clara.h |
||
3626 |
|||
3627 |
// Version 0.0.2.3 |
||
3628 |
|||
3629 |
// Only use header guard if we are not using an outer namespace |
||
3630 |
#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) |
||
3631 |
|||
3632 |
#ifndef STITCH_CLARA_OPEN_NAMESPACE |
||
3633 |
#define TWOBLUECUBES_CLARA_H_INCLUDED |
||
3634 |
#define STITCH_CLARA_OPEN_NAMESPACE |
||
3635 |
#define STITCH_CLARA_CLOSE_NAMESPACE |
||
3636 |
#else |
||
3637 |
#define STITCH_CLARA_CLOSE_NAMESPACE } |
||
3638 |
#endif |
||
3639 |
|||
3640 |
#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE |
||
3641 |
|||
3642 |
// ----------- #included from tbc_text_format.h ----------- |
||
3643 |
|||
3644 |
// Only use header guard if we are not using an outer namespace |
||
3645 |
#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) |
||
3646 |
#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE |
||
3647 |
#define TBC_TEXT_FORMAT_H_INCLUDED |
||
3648 |
#endif |
||
3649 |
|||
3650 |
#include <string> |
||
3651 |
#include <vector> |
||
3652 |
#include <sstream> |
||
3653 |
#include <algorithm> |
||
3654 |
|||
3655 |
// Use optional outer namespace |
||
3656 |
#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE |
||
3657 |
namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { |
||
3658 |
#endif |
||
3659 |
|||
3660 |
namespace Tbc { |
||
3661 |
|||
3662 |
#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH |
||
3663 |
const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; |
||
3664 |
#else |
||
3665 |
const unsigned int consoleWidth = 80; |
||
3666 |
#endif |
||
3667 |
|||
3668 |
struct TextAttributes { |
||
3669 |
TextAttributes() |
||
3670 |
: initialIndent( std::string::npos ), |
||
3671 |
indent( 0 ), |
||
3672 |
width( consoleWidth-1 ), |
||
3673 |
tabChar( '\t' ) |
||
3674 |
{} |
||
3675 |
|||
3676 |
TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } |
||
3677 |
TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } |
||
3678 |
TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } |
||
3679 |
TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } |
||
3680 |
|||
3681 |
std::size_t initialIndent; // indent of first line, or npos |
||
3682 |
std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos |
||
3683 |
std::size_t width; // maximum width of text, including indent. Longer text will wrap |
||
3684 |
char tabChar; // If this char is seen the indent is changed to current pos |
||
3685 |
}; |
||
3686 |
|||
3687 |
class Text { |
||
3688 |
public: |
||
3689 |
Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) |
||
3690 |
: attr( _attr ) |
||
3691 |
{ |
||
3692 |
std::string wrappableChars = " [({.,/|\\-"; |
||
3693 |
std::size_t indent = _attr.initialIndent != std::string::npos |
||
3694 |
? _attr.initialIndent |
||
3695 |
: _attr.indent; |
||
3696 |
std::string remainder = _str; |
||
3697 |
|||
3698 |
while( !remainder.empty() ) { |
||
3699 |
if( lines.size() >= 1000 ) { |
||
3700 |
lines.push_back( "... message truncated due to excessive size" ); |
||
3701 |
return; |
||
3702 |
} |
||
3703 |
std::size_t tabPos = std::string::npos; |
||
3704 |
std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); |
||
3705 |
std::size_t pos = remainder.find_first_of( '\n' ); |
||
3706 |
if( pos <= width ) { |
||
3707 |
width = pos; |
||
3708 |
} |
||
3709 |
pos = remainder.find_last_of( _attr.tabChar, width ); |
||
3710 |
if( pos != std::string::npos ) { |
||
3711 |
tabPos = pos; |
||
3712 |
if( remainder[width] == '\n' ) |
||
3713 |
width--; |
||
3714 |
remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); |
||
3715 |
} |
||
3716 |
|||
3717 |
if( width == remainder.size() ) { |
||
3718 |
spliceLine( indent, remainder, width ); |
||
3719 |
} |
||
3720 |
else if( remainder[width] == '\n' ) { |
||
3721 |
spliceLine( indent, remainder, width ); |
||
3722 |
if( width <= 1 || remainder.size() != 1 ) |
||
3723 |
remainder = remainder.substr( 1 ); |
||
3724 |
indent = _attr.indent; |
||
3725 |
} |
||
3726 |
else { |
||
3727 |
pos = remainder.find_last_of( wrappableChars, width ); |
||
3728 |
if( pos != std::string::npos && pos > 0 ) { |
||
3729 |
spliceLine( indent, remainder, pos ); |
||
3730 |
if( remainder[0] == ' ' ) |
||
3731 |
remainder = remainder.substr( 1 ); |
||
3732 |
} |
||
3733 |
else { |
||
3734 |
spliceLine( indent, remainder, width-1 ); |
||
3735 |
lines.back() += "-"; |
||
3736 |
} |
||
3737 |
if( lines.size() == 1 ) |
||
3738 |
indent = _attr.indent; |
||
3739 |
if( tabPos != std::string::npos ) |
||
3740 |
indent += tabPos; |
||
3741 |
} |
||
3742 |
} |
||
3743 |
} |
||
3744 |
|||
3745 |
void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { |
||
3746 |
lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); |
||
3747 |
_remainder = _remainder.substr( _pos ); |
||
3748 |
} |
||
3749 |
|||
3750 |
typedef std::vector<std::string>::const_iterator const_iterator; |
||
3751 |
|||
3752 |
const_iterator begin() const { return lines.begin(); } |
||
3753 |
const_iterator end() const { return lines.end(); } |
||
3754 |
std::string const& last() const { return lines.back(); } |
||
3755 |
std::size_t size() const { return lines.size(); } |
||
3756 |
std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } |
||
3757 |
std::string toString() const { |
||
3758 |
std::ostringstream oss; |
||
3759 |
oss << *this; |
||
3760 |
return oss.str(); |
||
3761 |
} |
||
3762 |
|||
3763 |
inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { |
||
3764 |
for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); |
||
3765 |
it != itEnd; ++it ) { |
||
3766 |
if( it != _text.begin() ) |
||
3767 |
_stream << "\n"; |
||
3768 |
_stream << *it; |
||
3769 |
} |
||
3770 |
return _stream; |
||
3771 |
} |
||
3772 |
|||
3773 |
private: |
||
3774 |
std::string str; |
||
3775 |
TextAttributes attr; |
||
3776 |
std::vector<std::string> lines; |
||
3777 |
}; |
||
3778 |
|||
3779 |
} // end namespace Tbc |
||
3780 |
|||
3781 |
#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE |
||
3782 |
} // end outer namespace |
||
3783 |
#endif |
||
3784 |
|||
3785 |
#endif // TBC_TEXT_FORMAT_H_INCLUDED |
||
3786 |
|||
3787 |
// ----------- end of #include from tbc_text_format.h ----------- |
||
3788 |
// ........... back in clara.h |
||
3789 |
|||
3790 |
#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE |
||
3791 |
|||
3792 |
// ----------- #included from clara_compilers.h ----------- |
||
3793 |
|||
3794 |
#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED |
||
3795 |
#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED |
||
3796 |
|||
3797 |
// Detect a number of compiler features - mostly C++11/14 conformance - by compiler |
||
3798 |
// The following features are defined: |
||
3799 |
// |
||
3800 |
// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? |
||
3801 |
// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? |
||
3802 |
// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods |
||
3803 |
// CLARA_CONFIG_CPP11_OVERRIDE : is override supported? |
||
3804 |
// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) |
||
3805 |
|||
3806 |
// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? |
||
3807 |
|||
3808 |
// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? |
||
3809 |
|||
3810 |
// In general each macro has a _NO_<feature name> form |
||
3811 |
// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. |
||
3812 |
// Many features, at point of detection, define an _INTERNAL_ macro, so they |
||
3813 |
// can be combined, en-mass, with the _NO_ forms later. |
||
3814 |
|||
3815 |
// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 |
||
3816 |
|||
3817 |
#ifdef __clang__ |
||
3818 |
|||
3819 |
#if __has_feature(cxx_nullptr) |
||
3820 |
#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR |
||
3821 |
#endif |
||
3822 |
|||
3823 |
#if __has_feature(cxx_noexcept) |
||
3824 |
#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT |
||
3825 |
#endif |
||
3826 |
|||
3827 |
#endif // __clang__ |
||
3828 |
|||
3829 |
//////////////////////////////////////////////////////////////////////////////// |
||
3830 |
// GCC |
||
3831 |
#ifdef __GNUC__ |
||
3832 |
|||
3833 |
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) |
||
3834 |
#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR |
||
3835 |
#endif |
||
3836 |
|||
3837 |
// - otherwise more recent versions define __cplusplus >= 201103L |
||
3838 |
// and will get picked up below |
||
3839 |
|||
3840 |
#endif // __GNUC__ |
||
3841 |
|||
3842 |
//////////////////////////////////////////////////////////////////////////////// |
||
3843 |
// Visual C++ |
||
3844 |
#ifdef _MSC_VER |
||
3845 |
|||
3846 |
#if (_MSC_VER >= 1600) |
||
3847 |
#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR |
||
3848 |
#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR |
||
3849 |
#endif |
||
3850 |
|||
3851 |
#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) |
||
3852 |
#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT |
||
3853 |
#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS |
||
3854 |
#endif |
||
3855 |
|||
3856 |
#endif // _MSC_VER |
||
3857 |
|||
3858 |
//////////////////////////////////////////////////////////////////////////////// |
||
3859 |
// C++ language feature support |
||
3860 |
|||
3861 |
// catch all support for C++11 |
||
3862 |
#if defined(__cplusplus) && __cplusplus >= 201103L |
||
3863 |
|||
3864 |
#define CLARA_CPP11_OR_GREATER |
||
3865 |
|||
3866 |
#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) |
||
3867 |
#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR |
||
3868 |
#endif |
||
3869 |
|||
3870 |
#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT |
||
3871 |
#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT |
||
3872 |
#endif |
||
3873 |
|||
3874 |
#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS |
||
3875 |
#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS |
||
3876 |
#endif |
||
3877 |
|||
3878 |
#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) |
||
3879 |
#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE |
||
3880 |
#endif |
||
3881 |
#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) |
||
3882 |
#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR |
||
3883 |
#endif |
||
3884 |
|||
3885 |
#endif // __cplusplus >= 201103L |
||
3886 |
|||
3887 |
// Now set the actual defines based on the above + anything the user has configured |
||
3888 |
#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) |
||
3889 |
#define CLARA_CONFIG_CPP11_NULLPTR |
||
3890 |
#endif |
||
3891 |
#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) |
||
3892 |
#define CLARA_CONFIG_CPP11_NOEXCEPT |
||
3893 |
#endif |
||
3894 |
#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) |
||
3895 |
#define CLARA_CONFIG_CPP11_GENERATED_METHODS |
||
3896 |
#endif |
||
3897 |
#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) |
||
3898 |
#define CLARA_CONFIG_CPP11_OVERRIDE |
||
3899 |
#endif |
||
3900 |
#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) |
||
3901 |
#define CLARA_CONFIG_CPP11_UNIQUE_PTR |
||
3902 |
#endif |
||
3903 |
|||
3904 |
// noexcept support: |
||
3905 |
#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) |
||
3906 |
#define CLARA_NOEXCEPT noexcept |
||
3907 |
# define CLARA_NOEXCEPT_IS(x) noexcept(x) |
||
3908 |
#else |
||
3909 |
#define CLARA_NOEXCEPT throw() |
||
3910 |
# define CLARA_NOEXCEPT_IS(x) |
||
3911 |
#endif |
||
3912 |
|||
3913 |
// nullptr support |
||
3914 |
#ifdef CLARA_CONFIG_CPP11_NULLPTR |
||
3915 |
#define CLARA_NULL nullptr |
||
3916 |
#else |
||
3917 |
#define CLARA_NULL NULL |
||
3918 |
#endif |
||
3919 |
|||
3920 |
// override support |
||
3921 |
#ifdef CLARA_CONFIG_CPP11_OVERRIDE |
||
3922 |
#define CLARA_OVERRIDE override |
||
3923 |
#else |
||
3924 |
#define CLARA_OVERRIDE |
||
3925 |
#endif |
||
3926 |
|||
3927 |
// unique_ptr support |
||
3928 |
#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR |
||
3929 |
# define CLARA_AUTO_PTR( T ) std::unique_ptr<T> |
||
3930 |
#else |
||
3931 |
# define CLARA_AUTO_PTR( T ) std::auto_ptr<T> |
||
3932 |
#endif |
||
3933 |
|||
3934 |
#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED |
||
3935 |
|||
3936 |
// ----------- end of #include from clara_compilers.h ----------- |
||
3937 |
// ........... back in clara.h |
||
3938 |
|||
3939 |
#include <map> |
||
3940 |
#include <stdexcept> |
||
3941 |
#include <memory> |
||
3942 |
|||
3943 |
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) |
||
3944 |
#define CLARA_PLATFORM_WINDOWS |
||
3945 |
#endif |
||
3946 |
|||
3947 |
// Use optional outer namespace |
||
3948 |
#ifdef STITCH_CLARA_OPEN_NAMESPACE |
||
3949 |
STITCH_CLARA_OPEN_NAMESPACE |
||
3950 |
#endif |
||
3951 |
|||
3952 |
namespace Clara { |
||
3953 |
|||
3954 |
struct UnpositionalTag {}; |
||
3955 |
|||
3956 |
extern UnpositionalTag _; |
||
3957 |
|||
3958 |
#ifdef CLARA_CONFIG_MAIN |
||
3959 |
UnpositionalTag _; |
||
3960 |
#endif |
||
3961 |
|||
3962 |
namespace Detail { |
||
3963 |
|||
3964 |
#ifdef CLARA_CONSOLE_WIDTH |
||
3965 |
const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; |
||
3966 |
#else |
||
3967 |
const unsigned int consoleWidth = 80; |
||
3968 |
#endif |
||
3969 |
|||
3970 |
using namespace Tbc; |
||
3971 |
|||
3972 |
56 |
inline bool startsWith( std::string const& str, std::string const& prefix ) { |
|
3973 |
✓✗✓✓ ✓✗ |
112 |
return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; |
3974 |
} |
||
3975 |
|||
3976 |
template<typename T> struct RemoveConstRef{ typedef T type; }; |
||
3977 |
template<typename T> struct RemoveConstRef<T&>{ typedef T type; }; |
||
3978 |
template<typename T> struct RemoveConstRef<T const&>{ typedef T type; }; |
||
3979 |
template<typename T> struct RemoveConstRef<T const>{ typedef T type; }; |
||
3980 |
|||
3981 |
template<typename T> struct IsBool { static const bool value = false; }; |
||
3982 |
template<> struct IsBool<bool> { static const bool value = true; }; |
||
3983 |
|||
3984 |
template<typename T> |
||
3985 |
void convertInto( std::string const& _source, T& _dest ) { |
||
3986 |
std::stringstream ss; |
||
3987 |
ss << _source; |
||
3988 |
ss >> _dest; |
||
3989 |
if( ss.fail() ) |
||
3990 |
throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); |
||
3991 |
} |
||
3992 |
inline void convertInto( std::string const& _source, std::string& _dest ) { |
||
3993 |
1 |
_dest = _source; |
|
3994 |
} |
||
3995 |
inline void convertInto( std::string const& _source, bool& _dest ) { |
||
3996 |
std::string sourceLC = _source; |
||
3997 |
std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); |
||
3998 |
if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) |
||
3999 |
_dest = true; |
||
4000 |
else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) |
||
4001 |
_dest = false; |
||
4002 |
else |
||
4003 |
throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); |
||
4004 |
} |
||
4005 |
|||
4006 |
template<typename ConfigT> |
||
4007 |
struct IArgFunction { |
||
4008 |
virtual ~IArgFunction() {} |
||
4009 |
#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS |
||
4010 |
IArgFunction() = default; |
||
4011 |
55 |
IArgFunction( IArgFunction const& ) = default; |
|
4012 |
#endif |
||
4013 |
virtual void set( ConfigT& config, std::string const& value ) const = 0; |
||
4014 |
virtual bool takesArg() const = 0; |
||
4015 |
virtual IArgFunction* clone() const = 0; |
||
4016 |
}; |
||
4017 |
|||
4018 |
template<typename ConfigT> |
||
4019 |
class BoundArgFunction { |
||
4020 |
public: |
||
4021 |
23 |
BoundArgFunction() : functionObj( CLARA_NULL ) {} |
|
4022 |
25 |
BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {} |
|
4023 |
✗✓✓✗ |
53 |
BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} |
4024 |
24 |
BoundArgFunction& operator = ( BoundArgFunction const& other ) { |
|
4025 |
✓✗ | 24 |
IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; |
4026 |
✓✓ | 24 |
delete functionObj; |
4027 |
24 |
functionObj = newFunctionObj; |
|
4028 |
24 |
return *this; |
|
4029 |
} |
||
4030 |
✗✗✓✗ ✗✗✓✗ ✗✗✓✗ ✗✗✓✗ ✗✗✓✗ ✗✗✓✗ ✗✗✓✓ ✓✗✗✗ ✓✗ |
101 |
~BoundArgFunction() { delete functionObj; } |
4031 |
|||
4032 |
void set( ConfigT& config, std::string const& value ) const { |
||
4033 |
✗✗✗✗ ✗✗✗✗ ✓✗ |
1 |
functionObj->set( config, value ); |
4034 |
} |
||
4035 |
bool takesArg() const { return functionObj->takesArg(); } |
||
4036 |
|||
4037 |
bool isSet() const { |
||
4038 |
22 |
return functionObj != CLARA_NULL; |
|
4039 |
} |
||
4040 |
private: |
||
4041 |
IArgFunction<ConfigT>* functionObj; |
||
4042 |
}; |
||
4043 |
|||
4044 |
template<typename C> |
||
4045 |
2 |
struct NullBinder : IArgFunction<C>{ |
|
4046 |
virtual void set( C&, std::string const& ) const {} |
||
4047 |
virtual bool takesArg() const { return true; } |
||
4048 |
virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); } |
||
4049 |
}; |
||
4050 |
|||
4051 |
template<typename C, typename M> |
||
4052 |
127 |
struct BoundDataMember : IArgFunction<C>{ |
|
4053 |
13 |
BoundDataMember( M C::* _member ) : member( _member ) {} |
|
4054 |
1 |
virtual void set( C& p, std::string const& stringValue ) const { |
|
4055 |
2 |
convertInto( stringValue, p.*member ); |
|
4056 |
1 |
} |
|
4057 |
virtual bool takesArg() const { return !IsBool<M>::value; } |
||
4058 |
76 |
virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); } |
|
4059 |
M C::* member; |
||
4060 |
}; |
||
4061 |
template<typename C, typename M> |
||
4062 |
struct BoundUnaryMethod : IArgFunction<C>{ |
||
4063 |
BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} |
||
4064 |
virtual void set( C& p, std::string const& stringValue ) const { |
||
4065 |
typename RemoveConstRef<M>::type value; |
||
4066 |
convertInto( stringValue, value ); |
||
4067 |
(p.*member)( value ); |
||
4068 |
} |
||
4069 |
virtual bool takesArg() const { return !IsBool<M>::value; } |
||
4070 |
virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); } |
||
4071 |
void (C::*member)( M ); |
||
4072 |
}; |
||
4073 |
template<typename C> |
||
4074 |
struct BoundNullaryMethod : IArgFunction<C>{ |
||
4075 |
BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} |
||
4076 |
virtual void set( C& p, std::string const& stringValue ) const { |
||
4077 |
bool value; |
||
4078 |
convertInto( stringValue, value ); |
||
4079 |
if( value ) |
||
4080 |
(p.*member)(); |
||
4081 |
} |
||
4082 |
virtual bool takesArg() const { return false; } |
||
4083 |
virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); } |
||
4084 |
void (C::*member)(); |
||
4085 |
}; |
||
4086 |
|||
4087 |
template<typename C> |
||
4088 |
11 |
struct BoundUnaryFunction : IArgFunction<C>{ |
|
4089 |
2 |
BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} |
|
4090 |
virtual void set( C& obj, std::string const& stringValue ) const { |
||
4091 |
bool value; |
||
4092 |
convertInto( stringValue, value ); |
||
4093 |
if( value ) |
||
4094 |
function( obj ); |
||
4095 |
} |
||
4096 |
virtual bool takesArg() const { return false; } |
||
4097 |
6 |
virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); } |
|
4098 |
void (*function)( C& ); |
||
4099 |
}; |
||
4100 |
|||
4101 |
template<typename C, typename T> |
||
4102 |
51 |
struct BoundBinaryFunction : IArgFunction<C>{ |
|
4103 |
9 |
BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} |
|
4104 |
virtual void set( C& obj, std::string const& stringValue ) const { |
||
4105 |
typename RemoveConstRef<T>::type value; |
||
4106 |
convertInto( stringValue, value ); |
||
4107 |
function( obj, value ); |
||
4108 |
} |
||
4109 |
virtual bool takesArg() const { return !IsBool<T>::value; } |
||
4110 |
28 |
virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); } |
|
4111 |
void (*function)( C&, T ); |
||
4112 |
}; |
||
4113 |
|||
4114 |
} // namespace Detail |
||
4115 |
|||
4116 |
1 |
inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) { |
|
4117 |
2 |
std::vector<std::string> args( static_cast<std::size_t>( argc ) ); |
|
4118 |
✓✓ | 2 |
for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i ) |
4119 |
3 |
args[i] = argv[i]; |
|
4120 |
|||
4121 |
1 |
return args; |
|
4122 |
} |
||
4123 |
|||
4124 |
class Parser { |
||
4125 |
enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; |
||
4126 |
Mode mode; |
||
4127 |
std::size_t from; |
||
4128 |
bool inQuotes; |
||
4129 |
public: |
||
4130 |
|||
4131 |
struct Token { |
||
4132 |
enum Type { Positional, ShortOpt, LongOpt }; |
||
4133 |
Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} |
||
4134 |
Type type; |
||
4135 |
std::string data; |
||
4136 |
}; |
||
4137 |
|||
4138 |
1 |
Parser() : mode( None ), from( 0 ), inQuotes( false ){} |
|
4139 |
|||
4140 |
1 |
void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) { |
|
4141 |
3 |
const std::string doubleDash = "--"; |
|
4142 |
✗✓✗✗ ✗✓ |
1 |
for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) |
4143 |
parseIntoTokens( args[i], tokens); |
||
4144 |
1 |
} |
|
4145 |
|||
4146 |
void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) { |
||
4147 |
for( std::size_t i = 0; i <= arg.size(); ++i ) { |
||
4148 |
char c = arg[i]; |
||
4149 |
if( c == '"' ) |
||
4150 |
inQuotes = !inQuotes; |
||
4151 |
mode = handleMode( i, c, arg, tokens ); |
||
4152 |
} |
||
4153 |
} |
||
4154 |
Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) { |
||
4155 |
switch( mode ) { |
||
4156 |
case None: return handleNone( i, c ); |
||
4157 |
case MaybeShortOpt: return handleMaybeShortOpt( i, c ); |
||
4158 |
case ShortOpt: |
||
4159 |
case LongOpt: |
||
4160 |
case SlashOpt: return handleOpt( i, c, arg, tokens ); |
||
4161 |
case Positional: return handlePositional( i, c, arg, tokens ); |
||
4162 |
default: throw std::logic_error( "Unknown mode" ); |
||
4163 |
} |
||
4164 |
} |
||
4165 |
|||
4166 |
Mode handleNone( std::size_t i, char c ) { |
||
4167 |
if( inQuotes ) { |
||
4168 |
from = i; |
||
4169 |
return Positional; |
||
4170 |
} |
||
4171 |
switch( c ) { |
||
4172 |
case '-': return MaybeShortOpt; |
||
4173 |
#ifdef CLARA_PLATFORM_WINDOWS |
||
4174 |
case '/': from = i+1; return SlashOpt; |
||
4175 |
#endif |
||
4176 |
default: from = i; return Positional; |
||
4177 |
} |
||
4178 |
} |
||
4179 |
Mode handleMaybeShortOpt( std::size_t i, char c ) { |
||
4180 |
switch( c ) { |
||
4181 |
case '-': from = i+1; return LongOpt; |
||
4182 |
default: from = i; return ShortOpt; |
||
4183 |
} |
||
4184 |
} |
||
4185 |
Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) { |
||
4186 |
if( std::string( " \t:=\0", 5 ).find( c ) == std::string::npos ) |
||
4187 |
return mode; |
||
4188 |
|||
4189 |
std::string optName = arg.substr( from, i-from ); |
||
4190 |
if( mode == ShortOpt ) |
||
4191 |
for( std::size_t j = 0; j < optName.size(); ++j ) |
||
4192 |
tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); |
||
4193 |
else if( mode == SlashOpt && optName.size() == 1 ) |
||
4194 |
tokens.push_back( Token( Token::ShortOpt, optName ) ); |
||
4195 |
else |
||
4196 |
tokens.push_back( Token( Token::LongOpt, optName ) ); |
||
4197 |
return None; |
||
4198 |
} |
||
4199 |
Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) { |
||
4200 |
if( inQuotes || std::string( " \t\0", 3 ).find( c ) == std::string::npos ) |
||
4201 |
return mode; |
||
4202 |
|||
4203 |
std::string data = arg.substr( from, i-from ); |
||
4204 |
tokens.push_back( Token( Token::Positional, data ) ); |
||
4205 |
return None; |
||
4206 |
} |
||
4207 |
}; |
||
4208 |
|||
4209 |
template<typename ConfigT> |
||
4210 |
645 |
struct CommonArgProperties { |
|
4211 |
115 |
CommonArgProperties() {} |
|
4212 |
CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {} |
||
4213 |
|||
4214 |
Detail::BoundArgFunction<ConfigT> boundField; |
||
4215 |
std::string description; |
||
4216 |
std::string detail; |
||
4217 |
std::string placeholder; // Only value if boundField takes an arg |
||
4218 |
|||
4219 |
bool takesArg() const { |
||
4220 |
return !placeholder.empty(); |
||
4221 |
} |
||
4222 |
22 |
void validate() const { |
|
4223 |
✗✓ | 44 |
if( !boundField.isSet() ) |
4224 |
throw std::logic_error( "option not bound" ); |
||
4225 |
22 |
} |
|
4226 |
}; |
||
4227 |
349 |
struct OptionArgProperties { |
|
4228 |
std::vector<std::string> shortNames; |
||
4229 |
std::string longName; |
||
4230 |
|||
4231 |
bool hasShortName( std::string const& shortName ) const { |
||
4232 |
return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); |
||
4233 |
} |
||
4234 |
bool hasLongName( std::string const& _longName ) const { |
||
4235 |
return _longName == longName; |
||
4236 |
} |
||
4237 |
}; |
||
4238 |
struct PositionalArgProperties { |
||
4239 |
23 |
PositionalArgProperties() : position( -1 ) {} |
|
4240 |
int position; // -1 means non-positional (floating) |
||
4241 |
|||
4242 |
bool isFixedPositional() const { |
||
4243 |
return position != -1; |
||
4244 |
} |
||
4245 |
}; |
||
4246 |
|||
4247 |
template<typename ConfigT> |
||
4248 |
4 |
class CommandLine { |
|
4249 |
|||
4250 |
✗✓ | 151 |
struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties { |
4251 |
92 |
Arg() {} |
|
4252 |
Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {} |
||
4253 |
|||
4254 |
using CommonArgProperties<ConfigT>::placeholder; // !TBD |
||
4255 |
|||
4256 |
std::string dbgName() const { |
||
4257 |
if( !longName.empty() ) |
||
4258 |
return "--" + longName; |
||
4259 |
if( !shortNames.empty() ) |
||
4260 |
return "-" + shortNames[0]; |
||
4261 |
return "positional args"; |
||
4262 |
} |
||
4263 |
std::string commands() const { |
||
4264 |
std::ostringstream oss; |
||
4265 |
bool first = true; |
||
4266 |
std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); |
||
4267 |
for(; it != itEnd; ++it ) { |
||
4268 |
if( first ) |
||
4269 |
first = false; |
||
4270 |
else |
||
4271 |
oss << ", "; |
||
4272 |
oss << "-" << *it; |
||
4273 |
} |
||
4274 |
if( !longName.empty() ) { |
||
4275 |
if( !first ) |
||
4276 |
oss << ", "; |
||
4277 |
oss << "--" << longName; |
||
4278 |
} |
||
4279 |
if( !placeholder.empty() ) |
||
4280 |
oss << " <" << placeholder << ">"; |
||
4281 |
return oss.str(); |
||
4282 |
} |
||
4283 |
}; |
||
4284 |
|||
4285 |
typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; |
||
4286 |
|||
4287 |
39 |
friend void addOptName( Arg& arg, std::string const& optName ) |
|
4288 |
{ |
||
4289 |
✓✗ | 39 |
if( optName.empty() ) |
4290 |
return; |
||
4291 |
✓✗✓✓ |
156 |
if( Detail::startsWith( optName, "--" ) ) { |
4292 |
✗✓ | 44 |
if( !arg.longName.empty() ) |
4293 |
throw std::logic_error( "Only one long opt may be specified. '" |
||
4294 |
+ arg.longName |
||
4295 |
+ "' already specified, now attempting to add '" |
||
4296 |
+ optName + "'" ); |
||
4297 |
44 |
arg.longName = optName.substr( 2 ); |
|
4298 |
} |
||
4299 |
✓✗✓✗ |
68 |
else if( Detail::startsWith( optName, "-" ) ) |
4300 |
51 |
arg.shortNames.push_back( optName.substr( 1 ) ); |
|
4301 |
else |
||
4302 |
throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); |
||
4303 |
} |
||
4304 |
friend void setPositionalArg( Arg& arg, int position ) |
||
4305 |
{ |
||
4306 |
arg.position = position; |
||
4307 |
} |
||
4308 |
|||
4309 |
class ArgBuilder { |
||
4310 |
public: |
||
4311 |
23 |
ArgBuilder( Arg* arg ) : m_arg( arg ) {} |
|
4312 |
|||
4313 |
// Bind a non-boolean data member (requires placeholder string) |
||
4314 |
template<typename C, typename M> |
||
4315 |
2 |
void bind( M C::* field, std::string const& placeholder ) { |
|
4316 |
✓✗ | 8 |
m_arg->boundField = new Detail::BoundDataMember<C,M>( field ); |
4317 |
4 |
m_arg->placeholder = placeholder; |
|
4318 |
2 |
} |
|
4319 |
// Bind a boolean data member (no placeholder required) |
||
4320 |
template<typename C> |
||
4321 |
10 |
void bind( bool C::* field ) { |
|
4322 |
✓✗ | 40 |
m_arg->boundField = new Detail::BoundDataMember<C,bool>( field ); |
4323 |
10 |
} |
|
4324 |
|||
4325 |
// Bind a method taking a single, non-boolean argument (requires a placeholder string) |
||
4326 |
template<typename C, typename M> |
||
4327 |
void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { |
||
4328 |
m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod ); |
||
4329 |
m_arg->placeholder = placeholder; |
||
4330 |
} |
||
4331 |
|||
4332 |
// Bind a method taking a single, boolean argument (no placeholder string required) |
||
4333 |
template<typename C> |
||
4334 |
void bind( void (C::* unaryMethod)( bool ) ) { |
||
4335 |
m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod ); |
||
4336 |
} |
||
4337 |
|||
4338 |
// Bind a method that takes no arguments (will be called if opt is present) |
||
4339 |
template<typename C> |
||
4340 |
void bind( void (C::* nullaryMethod)() ) { |
||
4341 |
m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod ); |
||
4342 |
} |
||
4343 |
|||
4344 |
// Bind a free function taking a single argument - the object to operate on (no placeholder string required) |
||
4345 |
template<typename C> |
||
4346 |
2 |
void bind( void (* unaryFunction)( C& ) ) { |
|
4347 |
✓✗ | 8 |
m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction ); |
4348 |
2 |
} |
|
4349 |
|||
4350 |
// Bind a free function taking a single argument - the object to operate on (requires a placeholder string) |
||
4351 |
template<typename C, typename T> |
||
4352 |
9 |
void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { |
|
4353 |
✓✗✓✗ ✓✗ |
36 |
m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction ); |
4354 |
18 |
m_arg->placeholder = placeholder; |
|
4355 |
9 |
} |
|
4356 |
|||
4357 |
ArgBuilder& describe( std::string const& description ) { |
||
4358 |
46 |
m_arg->description = description; |
|
4359 |
return *this; |
||
4360 |
} |
||
4361 |
ArgBuilder& detail( std::string const& detail ) { |
||
4362 |
m_arg->detail = detail; |
||
4363 |
return *this; |
||
4364 |
} |
||
4365 |
|||
4366 |
protected: |
||
4367 |
Arg* m_arg; |
||
4368 |
}; |
||
4369 |
|||
4370 |
class OptBuilder : public ArgBuilder { |
||
4371 |
public: |
||
4372 |
44 |
OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} |
|
4373 |
OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} |
||
4374 |
|||
4375 |
OptBuilder& operator[]( std::string const& optName ) { |
||
4376 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗ |
17 |
addOptName( *ArgBuilder::m_arg, optName ); |
4377 |
return *this; |
||
4378 |
} |
||
4379 |
}; |
||
4380 |
|||
4381 |
public: |
||
4382 |
|||
4383 |
1 |
CommandLine() |
|
4384 |
1 |
: m_boundProcessName( new Detail::NullBinder<ConfigT>() ), |
|
4385 |
m_highestSpecifiedArgPosition( 0 ), |
||
4386 |
5 |
m_throwOnUnrecognisedTokens( false ) |
|
4387 |
1 |
{} |
|
4388 |
CommandLine( CommandLine const& other ) |
||
4389 |
: m_boundProcessName( other.m_boundProcessName ), |
||
4390 |
m_options ( other.m_options ), |
||
4391 |
m_positionalArgs( other.m_positionalArgs ), |
||
4392 |
m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), |
||
4393 |
m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) |
||
4394 |
{ |
||
4395 |
if( other.m_floatingArg.get() ) |
||
4396 |
m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); |
||
4397 |
} |
||
4398 |
|||
4399 |
CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { |
||
4400 |
1 |
m_throwOnUnrecognisedTokens = shouldThrow; |
|
4401 |
return *this; |
||
4402 |
} |
||
4403 |
|||
4404 |
22 |
OptBuilder operator[]( std::string const& optName ) { |
|
4405 |
66 |
m_options.push_back( Arg() ); |
|
4406 |
44 |
addOptName( m_options.back(), optName ); |
|
4407 |
66 |
OptBuilder builder( &m_options.back() ); |
|
4408 |
22 |
return builder; |
|
4409 |
} |
||
4410 |
|||
4411 |
ArgBuilder operator[]( int position ) { |
||
4412 |
m_positionalArgs.insert( std::make_pair( position, Arg() ) ); |
||
4413 |
if( position > m_highestSpecifiedArgPosition ) |
||
4414 |
m_highestSpecifiedArgPosition = position; |
||
4415 |
setPositionalArg( m_positionalArgs[position], position ); |
||
4416 |
ArgBuilder builder( &m_positionalArgs[position] ); |
||
4417 |
return builder; |
||
4418 |
} |
||
4419 |
|||
4420 |
// Invoke this with the _ instance |
||
4421 |
1 |
ArgBuilder operator[]( UnpositionalTag ) { |
|
4422 |
✗✓ | 2 |
if( m_floatingArg.get() ) |
4423 |
throw std::logic_error( "Only one unpositional argument can be added" ); |
||
4424 |
3 |
m_floatingArg.reset( new Arg() ); |
|
4425 |
3 |
ArgBuilder builder( m_floatingArg.get() ); |
|
4426 |
1 |
return builder; |
|
4427 |
} |
||
4428 |
|||
4429 |
template<typename C, typename M> |
||
4430 |
1 |
void bindProcessName( M C::* field ) { |
|
4431 |
✓✗ | 4 |
m_boundProcessName = new Detail::BoundDataMember<C,M>( field ); |
4432 |
1 |
} |
|
4433 |
template<typename C, typename M> |
||
4434 |
void bindProcessName( void (C::*_unaryMethod)( M ) ) { |
||
4435 |
m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod ); |
||
4436 |
} |
||
4437 |
|||
4438 |
void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { |
||
4439 |
typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; |
||
4440 |
std::size_t maxWidth = 0; |
||
4441 |
for( it = itBegin; it != itEnd; ++it ) |
||
4442 |
maxWidth = (std::max)( maxWidth, it->commands().size() ); |
||
4443 |
|||
4444 |
for( it = itBegin; it != itEnd; ++it ) { |
||
4445 |
Detail::Text usage( it->commands(), Detail::TextAttributes() |
||
4446 |
.setWidth( maxWidth+indent ) |
||
4447 |
.setIndent( indent ) ); |
||
4448 |
Detail::Text desc( it->description, Detail::TextAttributes() |
||
4449 |
.setWidth( width - maxWidth - 3 ) ); |
||
4450 |
|||
4451 |
for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { |
||
4452 |
std::string usageCol = i < usage.size() ? usage[i] : ""; |
||
4453 |
os << usageCol; |
||
4454 |
|||
4455 |
if( i < desc.size() && !desc[i].empty() ) |
||
4456 |
os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) |
||
4457 |
<< desc[i]; |
||
4458 |
os << "\n"; |
||
4459 |
} |
||
4460 |
} |
||
4461 |
} |
||
4462 |
std::string optUsage() const { |
||
4463 |
std::ostringstream oss; |
||
4464 |
optUsage( oss ); |
||
4465 |
return oss.str(); |
||
4466 |
} |
||
4467 |
|||
4468 |
void argSynopsis( std::ostream& os ) const { |
||
4469 |
for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { |
||
4470 |
if( i > 1 ) |
||
4471 |
os << " "; |
||
4472 |
typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i ); |
||
4473 |
if( it != m_positionalArgs.end() ) |
||
4474 |
os << "<" << it->second.placeholder << ">"; |
||
4475 |
else if( m_floatingArg.get() ) |
||
4476 |
os << "<" << m_floatingArg->placeholder << ">"; |
||
4477 |
else |
||
4478 |
throw std::logic_error( "non consecutive positional arguments with no floating args" ); |
||
4479 |
} |
||
4480 |
// !TBD No indication of mandatory args |
||
4481 |
if( m_floatingArg.get() ) { |
||
4482 |
if( m_highestSpecifiedArgPosition > 1 ) |
||
4483 |
os << " "; |
||
4484 |
os << "[<" << m_floatingArg->placeholder << "> ...]"; |
||
4485 |
} |
||
4486 |
} |
||
4487 |
std::string argSynopsis() const { |
||
4488 |
std::ostringstream oss; |
||
4489 |
argSynopsis( oss ); |
||
4490 |
return oss.str(); |
||
4491 |
} |
||
4492 |
|||
4493 |
void usage( std::ostream& os, std::string const& procName ) const { |
||
4494 |
validate(); |
||
4495 |
os << "usage:\n " << procName << " "; |
||
4496 |
argSynopsis( os ); |
||
4497 |
if( !m_options.empty() ) { |
||
4498 |
os << " [options]\n\nwhere options are: \n"; |
||
4499 |
optUsage( os, 2 ); |
||
4500 |
} |
||
4501 |
os << "\n"; |
||
4502 |
} |
||
4503 |
std::string usage( std::string const& procName ) const { |
||
4504 |
std::ostringstream oss; |
||
4505 |
usage( oss, procName ); |
||
4506 |
return oss.str(); |
||
4507 |
} |
||
4508 |
|||
4509 |
ConfigT parse( std::vector<std::string> const& args ) const { |
||
4510 |
ConfigT config; |
||
4511 |
parseInto( args, config ); |
||
4512 |
return config; |
||
4513 |
} |
||
4514 |
|||
4515 |
1 |
std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const { |
|
4516 |
3 |
std::string processName = args[0]; |
|
4517 |
1 |
std::size_t lastSlash = processName.find_last_of( "/\\" ); |
|
4518 |
✓✗ | 1 |
if( lastSlash != std::string::npos ) |
4519 |
✓✗ | 2 |
processName = processName.substr( lastSlash+1 ); |
4520 |
2 |
m_boundProcessName.set( config, processName ); |
|
4521 |
2 |
std::vector<Parser::Token> tokens; |
|
4522 |
1 |
Parser parser; |
|
4523 |
✓✗ | 1 |
parser.parseIntoTokens( args, tokens ); |
4524 |
✓✗ | 2 |
return populate( tokens, config ); |
4525 |
} |
||
4526 |
|||
4527 |
1 |
std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { |
|
4528 |
1 |
validate(); |
|
4529 |
1 |
std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config ); |
|
4530 |
✓✗ | 2 |
unusedTokens = populateFixedArgs( unusedTokens, config ); |
4531 |
✓✗ | 2 |
unusedTokens = populateFloatingArgs( unusedTokens, config ); |
4532 |
1 |
return unusedTokens; |
|
4533 |
} |
||
4534 |
|||
4535 |
1 |
std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { |
|
4536 |
1 |
std::vector<Parser::Token> unusedTokens; |
|
4537 |
2 |
std::vector<std::string> errors; |
|
4538 |
✗✓ | 2 |
for( std::size_t i = 0; i < tokens.size(); ++i ) { |
4539 |
Parser::Token const& token = tokens[i]; |
||
4540 |
typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end(); |
||
4541 |
for(; it != itEnd; ++it ) { |
||
4542 |
Arg const& arg = *it; |
||
4543 |
|||
4544 |
try { |
||
4545 |
if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || |
||
4546 |
( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { |
||
4547 |
if( arg.takesArg() ) { |
||
4548 |
if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) |
||
4549 |
errors.push_back( "Expected argument to option: " + token.data ); |
||
4550 |
else |
||
4551 |
arg.boundField.set( config, tokens[++i].data ); |
||
4552 |
} |
||
4553 |
else { |
||
4554 |
arg.boundField.set( config, "true" ); |
||
4555 |
} |
||
4556 |
break; |
||
4557 |
} |
||
4558 |
} |
||
4559 |
catch( std::exception& ex ) { |
||
4560 |
errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); |
||
4561 |
} |
||
4562 |
} |
||
4563 |
if( it == itEnd ) { |
||
4564 |
if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) |
||
4565 |
unusedTokens.push_back( token ); |
||
4566 |
else if( errors.empty() && m_throwOnUnrecognisedTokens ) |
||
4567 |
errors.push_back( "unrecognised option: " + token.data ); |
||
4568 |
} |
||
4569 |
} |
||
4570 |
✗✓ | 1 |
if( !errors.empty() ) { |
4571 |
std::ostringstream oss; |
||
4572 |
for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end(); |
||
4573 |
it != itEnd; |
||
4574 |
++it ) { |
||
4575 |
if( it != errors.begin() ) |
||
4576 |
oss << "\n"; |
||
4577 |
oss << *it; |
||
4578 |
} |
||
4579 |
throw std::runtime_error( oss.str() ); |
||
4580 |
} |
||
4581 |
1 |
return unusedTokens; |
|
4582 |
} |
||
4583 |
1 |
std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { |
|
4584 |
1 |
std::vector<Parser::Token> unusedTokens; |
|
4585 |
1 |
int position = 1; |
|
4586 |
✗✓ | 2 |
for( std::size_t i = 0; i < tokens.size(); ++i ) { |
4587 |
Parser::Token const& token = tokens[i]; |
||
4588 |
typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position ); |
||
4589 |
if( it != m_positionalArgs.end() ) |
||
4590 |
it->second.boundField.set( config, token.data ); |
||
4591 |
else |
||
4592 |
unusedTokens.push_back( token ); |
||
4593 |
if( token.type == Parser::Token::Positional ) |
||
4594 |
position++; |
||
4595 |
} |
||
4596 |
1 |
return unusedTokens; |
|
4597 |
} |
||
4598 |
1 |
std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { |
|
4599 |
✗✓ | 2 |
if( !m_floatingArg.get() ) |
4600 |
return tokens; |
||
4601 |
2 |
std::vector<Parser::Token> unusedTokens; |
|
4602 |
✗✓ | 2 |
for( std::size_t i = 0; i < tokens.size(); ++i ) { |
4603 |
Parser::Token const& token = tokens[i]; |
||
4604 |
if( token.type == Parser::Token::Positional ) |
||
4605 |
m_floatingArg->boundField.set( config, token.data ); |
||
4606 |
else |
||
4607 |
unusedTokens.push_back( token ); |
||
4608 |
} |
||
4609 |
1 |
return unusedTokens; |
|
4610 |
} |
||
4611 |
|||
4612 |
1 |
void validate() const |
|
4613 |
{ |
||
4614 |
✗✓✗✗ ✗✗✓✗ |
2 |
if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) |
4615 |
throw std::logic_error( "No options or arguments specified" ); |
||
4616 |
|||
4617 |
✓✓ | 23 |
for( typename std::vector<Arg>::const_iterator it = m_options.begin(), |
4618 |
itEnd = m_options.end(); |
||
4619 |
it != itEnd; ++it ) |
||
4620 |
22 |
it->validate(); |
|
4621 |
1 |
} |
|
4622 |
|||
4623 |
private: |
||
4624 |
Detail::BoundArgFunction<ConfigT> m_boundProcessName; |
||
4625 |
std::vector<Arg> m_options; |
||
4626 |
std::map<int, Arg> m_positionalArgs; |
||
4627 |
ArgAutoPtr m_floatingArg; |
||
4628 |
int m_highestSpecifiedArgPosition; |
||
4629 |
bool m_throwOnUnrecognisedTokens; |
||
4630 |
}; |
||
4631 |
|||
4632 |
} // end namespace Clara |
||
4633 |
|||
4634 |
STITCH_CLARA_CLOSE_NAMESPACE |
||
4635 |
#undef STITCH_CLARA_OPEN_NAMESPACE |
||
4636 |
#undef STITCH_CLARA_CLOSE_NAMESPACE |
||
4637 |
|||
4638 |
#endif // TWOBLUECUBES_CLARA_H_INCLUDED |
||
4639 |
#undef STITCH_CLARA_OPEN_NAMESPACE |
||
4640 |
|||
4641 |
// Restore Clara's value for console width, if present |
||
4642 |
#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH |
||
4643 |
#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH |
||
4644 |
#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH |
||
4645 |
#endif |
||
4646 |
|||
4647 |
#include <fstream> |
||
4648 |
|||
4649 |
namespace Catch { |
||
4650 |
|||
4651 |
inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } |
||
4652 |
inline void abortAfterX( ConfigData& config, int x ) { |
||
4653 |
if( x < 1 ) |
||
4654 |
throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); |
||
4655 |
config.abortAfter = x; |
||
4656 |
} |
||
4657 |
inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } |
||
4658 |
inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } |
||
4659 |
|||
4660 |
inline void addWarning( ConfigData& config, std::string const& _warning ) { |
||
4661 |
if( _warning == "NoAssertions" ) |
||
4662 |
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions ); |
||
4663 |
else |
||
4664 |
throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); |
||
4665 |
} |
||
4666 |
inline void setOrder( ConfigData& config, std::string const& order ) { |
||
4667 |
if( startsWith( "declared", order ) ) |
||
4668 |
config.runOrder = RunTests::InDeclarationOrder; |
||
4669 |
else if( startsWith( "lexical", order ) ) |
||
4670 |
config.runOrder = RunTests::InLexicographicalOrder; |
||
4671 |
else if( startsWith( "random", order ) ) |
||
4672 |
config.runOrder = RunTests::InRandomOrder; |
||
4673 |
else |
||
4674 |
throw std::runtime_error( "Unrecognised ordering: '" + order + "'" ); |
||
4675 |
} |
||
4676 |
inline void setRngSeed( ConfigData& config, std::string const& seed ) { |
||
4677 |
if( seed == "time" ) { |
||
4678 |
config.rngSeed = static_cast<unsigned int>( std::time(0) ); |
||
4679 |
} |
||
4680 |
else { |
||
4681 |
std::stringstream ss; |
||
4682 |
ss << seed; |
||
4683 |
ss >> config.rngSeed; |
||
4684 |
if( ss.fail() ) |
||
4685 |
throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" ); |
||
4686 |
} |
||
4687 |
} |
||
4688 |
inline void setVerbosity( ConfigData& config, int level ) { |
||
4689 |
// !TBD: accept strings? |
||
4690 |
config.verbosity = static_cast<Verbosity::Level>( level ); |
||
4691 |
} |
||
4692 |
inline void setShowDurations( ConfigData& config, bool _showDurations ) { |
||
4693 |
config.showDurations = _showDurations |
||
4694 |
? ShowDurations::Always |
||
4695 |
: ShowDurations::Never; |
||
4696 |
} |
||
4697 |
inline void setUseColour( ConfigData& config, std::string const& value ) { |
||
4698 |
std::string mode = toLower( value ); |
||
4699 |
|||
4700 |
if( mode == "yes" ) |
||
4701 |
config.useColour = UseColour::Yes; |
||
4702 |
else if( mode == "no" ) |
||
4703 |
config.useColour = UseColour::No; |
||
4704 |
else if( mode == "auto" ) |
||
4705 |
config.useColour = UseColour::Auto; |
||
4706 |
else |
||
4707 |
throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); |
||
4708 |
} |
||
4709 |
inline void forceColour( ConfigData& config ) { |
||
4710 |
config.useColour = UseColour::Yes; |
||
4711 |
} |
||
4712 |
inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { |
||
4713 |
std::ifstream f( _filename.c_str() ); |
||
4714 |
if( !f.is_open() ) |
||
4715 |
throw std::domain_error( "Unable to load input file: " + _filename ); |
||
4716 |
|||
4717 |
std::string line; |
||
4718 |
while( std::getline( f, line ) ) { |
||
4719 |
line = trim(line); |
||
4720 |
if( !line.empty() && !startsWith( line, "#" ) ) |
||
4721 |
addTestOrTags( config, "\"" + line + "\"," ); |
||
4722 |
} |
||
4723 |
} |
||
4724 |
|||
4725 |
1 |
inline Clara::CommandLine<ConfigData> makeCommandLineParser() { |
|
4726 |
|||
4727 |
using namespace Clara; |
||
4728 |
1 |
CommandLine<ConfigData> cli; |
|
4729 |
|||
4730 |
✓✗ | 1 |
cli.bindProcessName( &ConfigData::processName ); |
4731 |
|||
4732 |
✓✗✓✗ ✓✗✓✗ |
13 |
cli["-?"]["-h"]["--help"] |
4733 |
✓✗ | 6 |
.describe( "display usage information" ) |
4734 |
✓✗ | 1 |
.bind( &ConfigData::showHelp ); |
4735 |
|||
4736 |
✓✗✓✗ ✓✗ |
9 |
cli["-l"]["--list-tests"] |
4737 |
✓✗ | 6 |
.describe( "list all/matching test cases" ) |
4738 |
✓✗ | 1 |
.bind( &ConfigData::listTests ); |
4739 |
|||
4740 |
✓✗✓✗ ✓✗ |
9 |
cli["-t"]["--list-tags"] |
4741 |
✓✗ | 6 |
.describe( "list all/matching tags" ) |
4742 |
✓✗ | 1 |
.bind( &ConfigData::listTags ); |
4743 |
|||
4744 |
✓✗✓✗ ✓✗ |
9 |
cli["-s"]["--success"] |
4745 |
✓✗ | 6 |
.describe( "include successful tests in output" ) |
4746 |
✓✗ | 1 |
.bind( &ConfigData::showSuccessfulTests ); |
4747 |
|||
4748 |
✓✗✓✗ ✓✗ |
9 |
cli["-b"]["--break"] |
4749 |
✓✗ | 6 |
.describe( "break into debugger on failure" ) |
4750 |
✓✗ | 1 |
.bind( &ConfigData::shouldDebugBreak ); |
4751 |
|||
4752 |
✓✗✓✗ ✓✗ |
9 |
cli["-e"]["--nothrow"] |
4753 |
✓✗ | 6 |
.describe( "skip exception tests" ) |
4754 |
✓✗ | 1 |
.bind( &ConfigData::noThrow ); |
4755 |
|||
4756 |
✓✗✓✗ ✓✗ |
9 |
cli["-i"]["--invisibles"] |
4757 |
✓✗ | 6 |
.describe( "show invisibles (tabs, newlines)" ) |
4758 |
✓✗ | 1 |
.bind( &ConfigData::showInvisibles ); |
4759 |
|||
4760 |
✓✗✓✗ ✓✗ |
9 |
cli["-o"]["--out"] |
4761 |
✓✗ | 6 |
.describe( "output filename" ) |
4762 |
✓✗✓✗ |
5 |
.bind( &ConfigData::outputFilename, "filename" ); |
4763 |
|||
4764 |
✓✗✓✗ ✓✗ |
9 |
cli["-r"]["--reporter"] |
4765 |
// .placeholder( "name[:filename]" ) |
||
4766 |
✓✗ | 6 |
.describe( "reporter to use (defaults to console)" ) |
4767 |
✓✗✓✗ |
5 |
.bind( &addReporterName, "name" ); |
4768 |
|||
4769 |
✓✗✓✗ ✓✗ |
9 |
cli["-n"]["--name"] |
4770 |
✓✗ | 6 |
.describe( "suite name" ) |
4771 |
✓✗✓✗ |
5 |
.bind( &ConfigData::name, "name" ); |
4772 |
|||
4773 |
✓✗✓✗ ✓✗ |
9 |
cli["-a"]["--abort"] |
4774 |
✓✗ | 6 |
.describe( "abort at first failure" ) |
4775 |
✓✗ | 1 |
.bind( &abortAfterFirst ); |
4776 |
|||
4777 |
✓✗✓✗ ✓✗ |
9 |
cli["-x"]["--abortx"] |
4778 |
✓✗ | 6 |
.describe( "abort after x failures" ) |
4779 |
✓✗✓✗ |
5 |
.bind( &abortAfterX, "no. failures" ); |
4780 |
|||
4781 |
✓✗✓✗ ✓✗ |
9 |
cli["-w"]["--warn"] |
4782 |
✓✗ | 6 |
.describe( "enable warnings" ) |
4783 |
✓✗✓✗ |
5 |
.bind( &addWarning, "warning name" ); |
4784 |
|||
4785 |
// - needs updating if reinstated |
||
4786 |
// cli.into( &setVerbosity ) |
||
4787 |
// .describe( "level of verbosity (0=no output)" ) |
||
4788 |
// .shortOpt( "v") |
||
4789 |
// .longOpt( "verbosity" ) |
||
4790 |
// .placeholder( "level" ); |
||
4791 |
|||
4792 |
✓✗ | 2 |
cli[_] |
4793 |
✓✗ | 5 |
.describe( "which test or tests to use" ) |
4794 |
✓✗✓✗ |
5 |
.bind( &addTestOrTags, "test name, pattern or tags" ); |
4795 |
|||
4796 |
✓✗✓✗ ✓✗ |
9 |
cli["-d"]["--durations"] |
4797 |
✓✗ | 6 |
.describe( "show test durations" ) |
4798 |
✓✗✓✗ |
5 |
.bind( &setShowDurations, "yes|no" ); |
4799 |
|||
4800 |
✓✗✓✗ ✓✗ |
9 |
cli["-f"]["--input-file"] |
4801 |
✓✗ | 6 |
.describe( "load test names to run from a file" ) |
4802 |
✓✗✓✗ |
5 |
.bind( &loadTestNamesFromFile, "filename" ); |
4803 |
|||
4804 |
✓✗✓✗ ✓✗ |
9 |
cli["-#"]["--filenames-as-tags"] |
4805 |
✓✗ | 6 |
.describe( "adds a tag for the filename" ) |
4806 |
✓✗ | 1 |
.bind( &ConfigData::filenamesAsTags ); |
4807 |
|||
4808 |
// Less common commands which don't have a short form |
||
4809 |
cli["--list-test-names-only"] |
||
4810 |
✓✗✓✗ ✓✗ |
9 |
.describe( "list all/matching test cases names only" ) |
4811 |
✓✗ | 1 |
.bind( &ConfigData::listTestNamesOnly ); |
4812 |
|||
4813 |
cli["--list-reporters"] |
||
4814 |
✓✗✓✗ ✓✗ |
9 |
.describe( "list all reporters" ) |
4815 |
✓✗ | 1 |
.bind( &ConfigData::listReporters ); |
4816 |
|||
4817 |
cli["--order"] |
||
4818 |
✓✗✓✗ ✓✗ |
9 |
.describe( "test case order (defaults to decl)" ) |
4819 |
✓✗✓✗ |
5 |
.bind( &setOrder, "decl|lex|rand" ); |
4820 |
|||
4821 |
cli["--rng-seed"] |
||
4822 |
✓✗✓✗ ✓✗ |
9 |
.describe( "set a specific seed for random numbers" ) |
4823 |
✓✗✓✗ |
5 |
.bind( &setRngSeed, "'time'|number" ); |
4824 |
|||
4825 |
cli["--force-colour"] |
||
4826 |
✓✗✓✗ ✓✗ |
9 |
.describe( "force colourised output (deprecated)" ) |
4827 |
✓✗ | 1 |
.bind( &forceColour ); |
4828 |
|||
4829 |
cli["--use-colour"] |
||
4830 |
✓✗✓✗ ✓✗ |
9 |
.describe( "should output be colourised" ) |
4831 |
✓✗✓✗ |
5 |
.bind( &setUseColour, "yes|no" ); |
4832 |
|||
4833 |
1 |
return cli; |
|
4834 |
} |
||
4835 |
|||
4836 |
} // end namespace Catch |
||
4837 |
|||
4838 |
// #included from: internal/catch_list.hpp |
||
4839 |
#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED |
||
4840 |
|||
4841 |
// #included from: catch_text.h |
||
4842 |
#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED |
||
4843 |
|||
4844 |
#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH |
||
4845 |
|||
4846 |
#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch |
||
4847 |
// #included from: ../external/tbc_text_format.h |
||
4848 |
// Only use header guard if we are not using an outer namespace |
||
4849 |
#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE |
||
4850 |
# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED |
||
4851 |
# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED |
||
4852 |
# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED |
||
4853 |
# endif |
||
4854 |
# else |
||
4855 |
# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED |
||
4856 |
# endif |
||
4857 |
#endif |
||
4858 |
#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED |
||
4859 |
#include <string> |
||
4860 |
#include <vector> |
||
4861 |
#include <sstream> |
||
4862 |
|||
4863 |
// Use optional outer namespace |
||
4864 |
#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE |
||
4865 |
namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { |
||
4866 |
#endif |
||
4867 |
|||
4868 |
namespace Tbc { |
||
4869 |
|||
4870 |
#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH |
||
4871 |
const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; |
||
4872 |
#else |
||
4873 |
const unsigned int consoleWidth = 80; |
||
4874 |
#endif |
||
4875 |
|||
4876 |
struct TextAttributes { |
||
4877 |
TextAttributes() |
||
4878 |
: initialIndent( std::string::npos ), |
||
4879 |
indent( 0 ), |
||
4880 |
width( consoleWidth-1 ), |
||
4881 |
tabChar( '\t' ) |
||
4882 |
{} |
||
4883 |
|||
4884 |
TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } |
||
4885 |
TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } |
||
4886 |
TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } |
||
4887 |
TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } |
||
4888 |
|||
4889 |
std::size_t initialIndent; // indent of first line, or npos |
||
4890 |
std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos |
||
4891 |
std::size_t width; // maximum width of text, including indent. Longer text will wrap |
||
4892 |
char tabChar; // If this char is seen the indent is changed to current pos |
||
4893 |
}; |
||
4894 |
|||
4895 |
class Text { |
||
4896 |
public: |
||
4897 |
Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) |
||
4898 |
: attr( _attr ) |
||
4899 |
{ |
||
4900 |
std::string wrappableChars = " [({.,/|\\-"; |
||
4901 |
std::size_t indent = _attr.initialIndent != std::string::npos |
||
4902 |
? _attr.initialIndent |
||
4903 |
: _attr.indent; |
||
4904 |
std::string remainder = _str; |
||
4905 |
|||
4906 |
while( !remainder.empty() ) { |
||
4907 |
if( lines.size() >= 1000 ) { |
||
4908 |
lines.push_back( "... message truncated due to excessive size" ); |
||
4909 |
return; |
||
4910 |
} |
||
4911 |
std::size_t tabPos = std::string::npos; |
||
4912 |
std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); |
||
4913 |
std::size_t pos = remainder.find_first_of( '\n' ); |
||
4914 |
if( pos <= width ) { |
||
4915 |
width = pos; |
||
4916 |
} |
||
4917 |
pos = remainder.find_last_of( _attr.tabChar, width ); |
||
4918 |
if( pos != std::string::npos ) { |
||
4919 |
tabPos = pos; |
||
4920 |
if( remainder[width] == '\n' ) |
||
4921 |
width--; |
||
4922 |
remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); |
||
4923 |
} |
||
4924 |
|||
4925 |
if( width == remainder.size() ) { |
||
4926 |
spliceLine( indent, remainder, width ); |
||
4927 |
} |
||
4928 |
else if( remainder[width] == '\n' ) { |
||
4929 |
spliceLine( indent, remainder, width ); |
||
4930 |
if( width <= 1 || remainder.size() != 1 ) |
||
4931 |
remainder = remainder.substr( 1 ); |
||
4932 |
indent = _attr.indent; |
||
4933 |
} |
||
4934 |
else { |
||
4935 |
pos = remainder.find_last_of( wrappableChars, width ); |
||
4936 |
if( pos != std::string::npos && pos > 0 ) { |
||
4937 |
spliceLine( indent, remainder, pos ); |
||
4938 |
if( remainder[0] == ' ' ) |
||
4939 |
remainder = remainder.substr( 1 ); |
||
4940 |
} |
||
4941 |
else { |
||
4942 |
spliceLine( indent, remainder, width-1 ); |
||
4943 |
lines.back() += "-"; |
||
4944 |
} |
||
4945 |
if( lines.size() == 1 ) |
||
4946 |
indent = _attr.indent; |
||
4947 |
if( tabPos != std::string::npos ) |
||
4948 |
indent += tabPos; |
||
4949 |
} |
||
4950 |
} |
||
4951 |
} |
||
4952 |
|||
4953 |
void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { |
||
4954 |
lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); |
||
4955 |
_remainder = _remainder.substr( _pos ); |
||
4956 |
} |
||
4957 |
|||
4958 |
typedef std::vector<std::string>::const_iterator const_iterator; |
||
4959 |
|||
4960 |
const_iterator begin() const { return lines.begin(); } |
||
4961 |
const_iterator end() const { return lines.end(); } |
||
4962 |
std::string const& last() const { return lines.back(); } |
||
4963 |
std::size_t size() const { return lines.size(); } |
||
4964 |
std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } |
||
4965 |
std::string toString() const { |
||
4966 |
std::ostringstream oss; |
||
4967 |
oss << *this; |
||
4968 |
return oss.str(); |
||
4969 |
} |
||
4970 |
|||
4971 |
inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { |
||
4972 |
for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); |
||
4973 |
it != itEnd; ++it ) { |
||
4974 |
if( it != _text.begin() ) |
||
4975 |
_stream << "\n"; |
||
4976 |
_stream << *it; |
||
4977 |
} |
||
4978 |
return _stream; |
||
4979 |
} |
||
4980 |
|||
4981 |
private: |
||
4982 |
std::string str; |
||
4983 |
TextAttributes attr; |
||
4984 |
std::vector<std::string> lines; |
||
4985 |
}; |
||
4986 |
|||
4987 |
} // end namespace Tbc |
||
4988 |
|||
4989 |
#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE |
||
4990 |
} // end outer namespace |
||
4991 |
#endif |
||
4992 |
|||
4993 |
#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED |
||
4994 |
#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE |
||
4995 |
|||
4996 |
namespace Catch { |
||
4997 |
using Tbc::Text; |
||
4998 |
using Tbc::TextAttributes; |
||
4999 |
} |
||
5000 |
|||
5001 |
// #included from: catch_console_colour.hpp |
||
5002 |
#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED |
||
5003 |
|||
5004 |
namespace Catch { |
||
5005 |
|||
5006 |
struct Colour { |
||
5007 |
enum Code { |
||
5008 |
None = 0, |
||
5009 |
|||
5010 |
White, |
||
5011 |
Red, |
||
5012 |
Green, |
||
5013 |
Blue, |
||
5014 |
Cyan, |
||
5015 |
Yellow, |
||
5016 |
Grey, |
||
5017 |
|||
5018 |
Bright = 0x10, |
||
5019 |
|||
5020 |
BrightRed = Bright | Red, |
||
5021 |
BrightGreen = Bright | Green, |
||
5022 |
LightGrey = Bright | Grey, |
||
5023 |
BrightWhite = Bright | White, |
||
5024 |
|||
5025 |
// By intention |
||
5026 |
FileName = LightGrey, |
||
5027 |
Warning = Yellow, |
||
5028 |
ResultError = BrightRed, |
||
5029 |
ResultSuccess = BrightGreen, |
||
5030 |
ResultExpectedFailure = Warning, |
||
5031 |
|||
5032 |
Error = BrightRed, |
||
5033 |
Success = Green, |
||
5034 |
|||
5035 |
OriginalExpression = Cyan, |
||
5036 |
ReconstructedExpression = Yellow, |
||
5037 |
|||
5038 |
SecondaryText = LightGrey, |
||
5039 |
Headers = White |
||
5040 |
}; |
||
5041 |
|||
5042 |
// Use constructed object for RAII guard |
||
5043 |
Colour( Code _colourCode ); |
||
5044 |
Colour( Colour const& other ); |
||
5045 |
~Colour(); |
||
5046 |
|||
5047 |
// Use static method for one-shot changes |
||
5048 |
static void use( Code _colourCode ); |
||
5049 |
|||
5050 |
private: |
||
5051 |
bool m_moved; |
||
5052 |
}; |
||
5053 |
|||
5054 |
inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } |
||
5055 |
|||
5056 |
} // end namespace Catch |
||
5057 |
|||
5058 |
// #included from: catch_interfaces_reporter.h |
||
5059 |
#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED |
||
5060 |
|||
5061 |
#include <string> |
||
5062 |
#include <ostream> |
||
5063 |
#include <map> |
||
5064 |
#include <assert.h> |
||
5065 |
|||
5066 |
namespace Catch |
||
5067 |
{ |
||
5068 |
2 |
struct ReporterConfig { |
|
5069 |
explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig ) |
||
5070 |
✗✗ | 3 |
: m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} |
5071 |
|||
5072 |
ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream ) |
||
5073 |
: m_stream( &_stream ), m_fullConfig( _fullConfig ) {} |
||
5074 |
|||
5075 |
std::ostream& stream() const { return *m_stream; } |
||
5076 |
2 |
Ptr<IConfig const> fullConfig() const { return m_fullConfig; } |
|
5077 |
|||
5078 |
private: |
||
5079 |
std::ostream* m_stream; |
||
5080 |
Ptr<IConfig const> m_fullConfig; |
||
5081 |
}; |
||
5082 |
|||
5083 |
struct ReporterPreferences { |
||
5084 |
ReporterPreferences() |
||
5085 |
1 |
: shouldRedirectStdOut( false ) |
|
5086 |
{} |
||
5087 |
|||
5088 |
bool shouldRedirectStdOut; |
||
5089 |
}; |
||
5090 |
|||
5091 |
template<typename T> |
||
5092 |
6 |
struct LazyStat : Option<T> { |
|
5093 |
6 |
LazyStat() : used( false ) {} |
|
5094 |
LazyStat& operator=( T const& _value ) { |
||
5095 |
396 |
Option<T>::operator=( _value ); |
|
5096 |
396 |
used = false; |
|
5097 |
return *this; |
||
5098 |
} |
||
5099 |
void reset() { |
||
5100 |
398 |
Option<T>::reset(); |
|
5101 |
398 |
used = false; |
|
5102 |
} |
||
5103 |
bool used; |
||
5104 |
}; |
||
5105 |
|||
5106 |
9 |
struct TestRunInfo { |
|
5107 |
2 |
TestRunInfo( std::string const& _name ) : name( _name ) {} |
|
5108 |
std::string name; |
||
5109 |
}; |
||
5110 |
12 |
struct GroupInfo { |
|
5111 |
GroupInfo( std::string const& _name, |
||
5112 |
std::size_t _groupIndex, |
||
5113 |
std::size_t _groupsCount ) |
||
5114 |
2 |
: name( _name ), |
|
5115 |
groupIndex( _groupIndex ), |
||
5116 |
4 |
groupsCounts( _groupsCount ) |
|
5117 |
{} |
||
5118 |
|||
5119 |
std::string name; |
||
5120 |
std::size_t groupIndex; |
||
5121 |
std::size_t groupsCounts; |
||
5122 |
}; |
||
5123 |
|||
5124 |
struct AssertionStats { |
||
5125 |
1432923 |
AssertionStats( AssertionResult const& _assertionResult, |
|
5126 |
std::vector<MessageInfo> const& _infoMessages, |
||
5127 |
Totals const& _totals ) |
||
5128 |
1432923 |
: assertionResult( _assertionResult ), |
|
5129 |
infoMessages( _infoMessages ), |
||
5130 |
✓✗ | 1432923 |
totals( _totals ) |
5131 |
{ |
||
5132 |
✗✓ | 2865846 |
if( assertionResult.hasMessage() ) { |
5133 |
// Copy message into messages list. |
||
5134 |
// !TBD This should have been done earlier, somewhere |
||
5135 |
MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); |
||
5136 |
builder << assertionResult.getMessage(); |
||
5137 |
builder.m_info.message = builder.m_stream.str(); |
||
5138 |
|||
5139 |
infoMessages.push_back( builder.m_info ); |
||
5140 |
} |
||
5141 |
1432923 |
} |
|
5142 |
virtual ~AssertionStats(); |
||
5143 |
|||
5144 |
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS |
||
5145 |
AssertionStats( AssertionStats const& ) = default; |
||
5146 |
AssertionStats( AssertionStats && ) = default; |
||
5147 |
AssertionStats& operator = ( AssertionStats const& ) = default; |
||
5148 |
AssertionStats& operator = ( AssertionStats && ) = default; |
||
5149 |
# endif |
||
5150 |
|||
5151 |
AssertionResult assertionResult; |
||
5152 |
std::vector<MessageInfo> infoMessages; |
||
5153 |
Totals totals; |
||
5154 |
}; |
||
5155 |
|||
5156 |
struct SectionStats { |
||
5157 |
SectionStats( SectionInfo const& _sectionInfo, |
||
5158 |
Counts const& _assertions, |
||
5159 |
double _durationInSeconds, |
||
5160 |
bool _missingAssertions ) |
||
5161 |
1145 |
: sectionInfo( _sectionInfo ), |
|
5162 |
assertions( _assertions ), |
||
5163 |
durationInSeconds( _durationInSeconds ), |
||
5164 |
✓✗✗✗ |
1145 |
missingAssertions( _missingAssertions ) |
5165 |
{} |
||
5166 |
virtual ~SectionStats(); |
||
5167 |
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS |
||
5168 |
SectionStats( SectionStats const& ) = default; |
||
5169 |
SectionStats( SectionStats && ) = default; |
||
5170 |
SectionStats& operator = ( SectionStats const& ) = default; |
||
5171 |
SectionStats& operator = ( SectionStats && ) = default; |
||
5172 |
# endif |
||
5173 |
|||
5174 |
SectionInfo sectionInfo; |
||
5175 |
Counts assertions; |
||
5176 |
double durationInSeconds; |
||
5177 |
bool missingAssertions; |
||
5178 |
}; |
||
5179 |
|||
5180 |
struct TestCaseStats { |
||
5181 |
394 |
TestCaseStats( TestCaseInfo const& _testInfo, |
|
5182 |
Totals const& _totals, |
||
5183 |
std::string const& _stdOut, |
||
5184 |
std::string const& _stdErr, |
||
5185 |
bool _aborting ) |
||
5186 |
394 |
: testInfo( _testInfo ), |
|
5187 |
totals( _totals ), |
||
5188 |
stdOut( _stdOut ), |
||
5189 |
stdErr( _stdErr ), |
||
5190 |
1182 |
aborting( _aborting ) |
|
5191 |
394 |
{} |
|
5192 |
virtual ~TestCaseStats(); |
||
5193 |
|||
5194 |
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS |
||
5195 |
TestCaseStats( TestCaseStats const& ) = default; |
||
5196 |
TestCaseStats( TestCaseStats && ) = default; |
||
5197 |
TestCaseStats& operator = ( TestCaseStats const& ) = default; |
||
5198 |
TestCaseStats& operator = ( TestCaseStats && ) = default; |
||
5199 |
# endif |
||
5200 |
|||
5201 |
TestCaseInfo testInfo; |
||
5202 |
Totals totals; |
||
5203 |
std::string stdOut; |
||
5204 |
std::string stdErr; |
||
5205 |
bool aborting; |
||
5206 |
}; |
||
5207 |
|||
5208 |
struct TestGroupStats { |
||
5209 |
1 |
TestGroupStats( GroupInfo const& _groupInfo, |
|
5210 |
Totals const& _totals, |
||
5211 |
bool _aborting ) |
||
5212 |
1 |
: groupInfo( _groupInfo ), |
|
5213 |
totals( _totals ), |
||
5214 |
2 |
aborting( _aborting ) |
|
5215 |
1 |
{} |
|
5216 |
TestGroupStats( GroupInfo const& _groupInfo ) |
||
5217 |
: groupInfo( _groupInfo ), |
||
5218 |
aborting( false ) |
||
5219 |
{} |
||
5220 |
virtual ~TestGroupStats(); |
||
5221 |
|||
5222 |
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS |
||
5223 |
TestGroupStats( TestGroupStats const& ) = default; |
||
5224 |
TestGroupStats( TestGroupStats && ) = default; |
||
5225 |
TestGroupStats& operator = ( TestGroupStats const& ) = default; |
||
5226 |
TestGroupStats& operator = ( TestGroupStats && ) = default; |
||
5227 |
# endif |
||
5228 |
|||
5229 |
GroupInfo groupInfo; |
||
5230 |
Totals totals; |
||
5231 |
bool aborting; |
||
5232 |
}; |
||
5233 |
|||
5234 |
struct TestRunStats { |
||
5235 |
TestRunStats( TestRunInfo const& _runInfo, |
||
5236 |
Totals const& _totals, |
||
5237 |
bool _aborting ) |
||
5238 |
1 |
: runInfo( _runInfo ), |
|
5239 |
totals( _totals ), |
||
5240 |
2 |
aborting( _aborting ) |
|
5241 |
{} |
||
5242 |
virtual ~TestRunStats(); |
||
5243 |
|||
5244 |
# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS |
||
5245 |
TestRunStats( TestRunStats const& _other ) |
||
5246 |
: runInfo( _other.runInfo ), |
||
5247 |
totals( _other.totals ), |
||
5248 |
aborting( _other.aborting ) |
||
5249 |
{} |
||
5250 |
# else |
||
5251 |
TestRunStats( TestRunStats const& ) = default; |
||
5252 |
TestRunStats( TestRunStats && ) = default; |
||
5253 |
TestRunStats& operator = ( TestRunStats const& ) = default; |
||
5254 |
TestRunStats& operator = ( TestRunStats && ) = default; |
||
5255 |
# endif |
||
5256 |
|||
5257 |
TestRunInfo runInfo; |
||
5258 |
Totals totals; |
||
5259 |
bool aborting; |
||
5260 |
}; |
||
5261 |
|||
5262 |
class MultipleReporters; |
||
5263 |
|||
5264 |
2 |
struct IStreamingReporter : IShared { |
|
5265 |
virtual ~IStreamingReporter(); |
||
5266 |
|||
5267 |
// Implementing class must also provide the following static method: |
||
5268 |
// static std::string getDescription(); |
||
5269 |
|||
5270 |
virtual ReporterPreferences getPreferences() const = 0; |
||
5271 |
|||
5272 |
virtual void noMatchingTestCases( std::string const& spec ) = 0; |
||
5273 |
|||
5274 |
virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; |
||
5275 |
virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; |
||
5276 |
|||
5277 |
virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; |
||
5278 |
virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; |
||
5279 |
|||
5280 |
virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; |
||
5281 |
|||
5282 |
// The return value indicates if the messages buffer should be cleared: |
||
5283 |
virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; |
||
5284 |
|||
5285 |
virtual void sectionEnded( SectionStats const& sectionStats ) = 0; |
||
5286 |
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; |
||
5287 |
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; |
||
5288 |
virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; |
||
5289 |
|||
5290 |
virtual void skipTest( TestCaseInfo const& testInfo ) = 0; |
||
5291 |
|||
5292 |
virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } |
||
5293 |
}; |
||
5294 |
|||
5295 |
8 |
struct IReporterFactory : IShared { |
|
5296 |
virtual ~IReporterFactory(); |
||
5297 |
virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; |
||
5298 |
virtual std::string getDescription() const = 0; |
||
5299 |
}; |
||
5300 |
|||
5301 |
struct IReporterRegistry { |
||
5302 |
typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap; |
||
5303 |
typedef std::vector<Ptr<IReporterFactory> > Listeners; |
||
5304 |
|||
5305 |
virtual ~IReporterRegistry(); |
||
5306 |
virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0; |
||
5307 |
virtual FactoryMap const& getFactories() const = 0; |
||
5308 |
virtual Listeners const& getListeners() const = 0; |
||
5309 |
}; |
||
5310 |
|||
5311 |
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ); |
||
5312 |
|||
5313 |
} |
||
5314 |
|||
5315 |
#include <limits> |
||
5316 |
#include <algorithm> |
||
5317 |
|||
5318 |
namespace Catch { |
||
5319 |
|||
5320 |
inline std::size_t listTests( Config const& config ) { |
||
5321 |
|||
5322 |
TestSpec testSpec = config.testSpec(); |
||
5323 |
if( config.testSpec().hasFilters() ) |
||
5324 |
Catch::cout() << "Matching test cases:\n"; |
||
5325 |
else { |
||
5326 |
Catch::cout() << "All available test cases:\n"; |
||
5327 |
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); |
||
5328 |
} |
||
5329 |
|||
5330 |
std::size_t matchedTests = 0; |
||
5331 |
TextAttributes nameAttr, tagsAttr; |
||
5332 |
nameAttr.setInitialIndent( 2 ).setIndent( 4 ); |
||
5333 |
tagsAttr.setIndent( 6 ); |
||
5334 |
|||
5335 |
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); |
||
5336 |
for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); |
||
5337 |
it != itEnd; |
||
5338 |
++it ) { |
||
5339 |
matchedTests++; |
||
5340 |
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); |
||
5341 |
Colour::Code colour = testCaseInfo.isHidden() |
||
5342 |
? Colour::SecondaryText |
||
5343 |
: Colour::None; |
||
5344 |
Colour colourGuard( colour ); |
||
5345 |
|||
5346 |
Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; |
||
5347 |
if( !testCaseInfo.tags.empty() ) |
||
5348 |
Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; |
||
5349 |
} |
||
5350 |
|||
5351 |
if( !config.testSpec().hasFilters() ) |
||
5352 |
Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl; |
||
5353 |
else |
||
5354 |
Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; |
||
5355 |
return matchedTests; |
||
5356 |
} |
||
5357 |
|||
5358 |
inline std::size_t listTestsNamesOnly( Config const& config ) { |
||
5359 |
TestSpec testSpec = config.testSpec(); |
||
5360 |
if( !config.testSpec().hasFilters() ) |
||
5361 |
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); |
||
5362 |
std::size_t matchedTests = 0; |
||
5363 |
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); |
||
5364 |
for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); |
||
5365 |
it != itEnd; |
||
5366 |
++it ) { |
||
5367 |
matchedTests++; |
||
5368 |
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); |
||
5369 |
Catch::cout() << testCaseInfo.name << std::endl; |
||
5370 |
} |
||
5371 |
return matchedTests; |
||
5372 |
} |
||
5373 |
|||
5374 |
struct TagInfo { |
||
5375 |
TagInfo() : count ( 0 ) {} |
||
5376 |
void add( std::string const& spelling ) { |
||
5377 |
++count; |
||
5378 |
spellings.insert( spelling ); |
||
5379 |
} |
||
5380 |
std::string all() const { |
||
5381 |
std::string out; |
||
5382 |
for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end(); |
||
5383 |
it != itEnd; |
||
5384 |
++it ) |
||
5385 |
out += "[" + *it + "]"; |
||
5386 |
return out; |
||
5387 |
} |
||
5388 |
std::set<std::string> spellings; |
||
5389 |
std::size_t count; |
||
5390 |
}; |
||
5391 |
|||
5392 |
inline std::size_t listTags( Config const& config ) { |
||
5393 |
TestSpec testSpec = config.testSpec(); |
||
5394 |
if( config.testSpec().hasFilters() ) |
||
5395 |
Catch::cout() << "Tags for matching test cases:\n"; |
||
5396 |
else { |
||
5397 |
Catch::cout() << "All available tags:\n"; |
||
5398 |
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); |
||
5399 |
} |
||
5400 |
|||
5401 |
std::map<std::string, TagInfo> tagCounts; |
||
5402 |
|||
5403 |
std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); |
||
5404 |
for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); |
||
5405 |
it != itEnd; |
||
5406 |
++it ) { |
||
5407 |
for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), |
||
5408 |
tagItEnd = it->getTestCaseInfo().tags.end(); |
||
5409 |
tagIt != tagItEnd; |
||
5410 |
++tagIt ) { |
||
5411 |
std::string tagName = *tagIt; |
||
5412 |
std::string lcaseTagName = toLower( tagName ); |
||
5413 |
std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName ); |
||
5414 |
if( countIt == tagCounts.end() ) |
||
5415 |
countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; |
||
5416 |
countIt->second.add( tagName ); |
||
5417 |
} |
||
5418 |
} |
||
5419 |
|||
5420 |
for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(), |
||
5421 |
countItEnd = tagCounts.end(); |
||
5422 |
countIt != countItEnd; |
||
5423 |
++countIt ) { |
||
5424 |
std::ostringstream oss; |
||
5425 |
oss << " " << std::setw(2) << countIt->second.count << " "; |
||
5426 |
Text wrapper( countIt->second.all(), TextAttributes() |
||
5427 |
.setInitialIndent( 0 ) |
||
5428 |
.setIndent( oss.str().size() ) |
||
5429 |
.setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); |
||
5430 |
Catch::cout() << oss.str() << wrapper << "\n"; |
||
5431 |
} |
||
5432 |
Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; |
||
5433 |
return tagCounts.size(); |
||
5434 |
} |
||
5435 |
|||
5436 |
inline std::size_t listReporters( Config const& /*config*/ ) { |
||
5437 |
Catch::cout() << "Available reporters:\n"; |
||
5438 |
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); |
||
5439 |
IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; |
||
5440 |
std::size_t maxNameLen = 0; |
||
5441 |
for(it = itBegin; it != itEnd; ++it ) |
||
5442 |
maxNameLen = (std::max)( maxNameLen, it->first.size() ); |
||
5443 |
|||
5444 |
for(it = itBegin; it != itEnd; ++it ) { |
||
5445 |
Text wrapper( it->second->getDescription(), TextAttributes() |
||
5446 |
.setInitialIndent( 0 ) |
||
5447 |
.setIndent( 7+maxNameLen ) |
||
5448 |
.setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); |
||
5449 |
Catch::cout() << " " |
||
5450 |
<< it->first |
||
5451 |
<< ":" |
||
5452 |
<< std::string( maxNameLen - it->first.size() + 2, ' ' ) |
||
5453 |
<< wrapper << "\n"; |
||
5454 |
} |
||
5455 |
Catch::cout() << std::endl; |
||
5456 |
return factories.size(); |
||
5457 |
} |
||
5458 |
|||
5459 |
1 |
inline Option<std::size_t> list( Config const& config ) { |
|
5460 |
1 |
Option<std::size_t> listedCount; |
|
5461 |
✗✓ | 1 |
if( config.listTests() ) |
5462 |
listedCount = listedCount.valueOr(0) + listTests( config ); |
||
5463 |
✗✓ | 1 |
if( config.listTestNamesOnly() ) |
5464 |
listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); |
||
5465 |
✗✓ | 1 |
if( config.listTags() ) |
5466 |
listedCount = listedCount.valueOr(0) + listTags( config ); |
||
5467 |
✗✓ | 1 |
if( config.listReporters() ) |
5468 |
listedCount = listedCount.valueOr(0) + listReporters( config ); |
||
5469 |
1 |
return listedCount; |
|
5470 |
} |
||
5471 |
|||
5472 |
} // end namespace Catch |
||
5473 |
|||
5474 |
// #included from: internal/catch_run_context.hpp |
||
5475 |
#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED |
||
5476 |
|||
5477 |
// #included from: catch_test_case_tracker.hpp |
||
5478 |
#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED |
||
5479 |
|||
5480 |
#include <map> |
||
5481 |
#include <string> |
||
5482 |
#include <assert.h> |
||
5483 |
#include <vector> |
||
5484 |
|||
5485 |
namespace Catch { |
||
5486 |
namespace TestCaseTracking { |
||
5487 |
|||
5488 |
2376 |
struct ITracker : SharedImpl<> { |
|
5489 |
virtual ~ITracker(); |
||
5490 |
|||
5491 |
// static queries |
||
5492 |
virtual std::string name() const = 0; |
||
5493 |
|||
5494 |
// dynamic queries |
||
5495 |
virtual bool isComplete() const = 0; // Successfully completed or failed |
||
5496 |
virtual bool isSuccessfullyCompleted() const = 0; |
||
5497 |
virtual bool isOpen() const = 0; // Started but not complete |
||
5498 |
virtual bool hasChildren() const = 0; |
||
5499 |
|||
5500 |
virtual ITracker& parent() = 0; |
||
5501 |
|||
5502 |
// actions |
||
5503 |
virtual void close() = 0; // Successfully complete |
||
5504 |
virtual void fail() = 0; |
||
5505 |
virtual void markAsNeedingAnotherRun() = 0; |
||
5506 |
|||
5507 |
virtual void addChild( Ptr<ITracker> const& child ) = 0; |
||
5508 |
virtual ITracker* findChild( std::string const& name ) = 0; |
||
5509 |
virtual void openChild() = 0; |
||
5510 |
|||
5511 |
// Debug/ checking |
||
5512 |
virtual bool isSectionTracker() const = 0; |
||
5513 |
virtual bool isIndexTracker() const = 0; |
||
5514 |
}; |
||
5515 |
|||
5516 |
2 |
class TrackerContext { |
|
5517 |
|||
5518 |
enum RunState { |
||
5519 |
NotStarted, |
||
5520 |
Executing, |
||
5521 |
CompletedCycle |
||
5522 |
}; |
||
5523 |
|||
5524 |
Ptr<ITracker> m_rootTracker; |
||
5525 |
ITracker* m_currentTracker; |
||
5526 |
RunState m_runState; |
||
5527 |
|||
5528 |
public: |
||
5529 |
|||
5530 |
static TrackerContext& instance() { |
||
5531 |
static TrackerContext s_instance; |
||
5532 |
return s_instance; |
||
5533 |
} |
||
5534 |
|||
5535 |
TrackerContext() |
||
5536 |
1 |
: m_currentTracker( CATCH_NULL ), |
|
5537 |
2 |
m_runState( NotStarted ) |
|
5538 |
{} |
||
5539 |
|||
5540 |
ITracker& startRun(); |
||
5541 |
|||
5542 |
void endRun() { |
||
5543 |
m_rootTracker.reset(); |
||
5544 |
m_currentTracker = CATCH_NULL; |
||
5545 |
m_runState = NotStarted; |
||
5546 |
} |
||
5547 |
|||
5548 |
void startCycle() { |
||
5549 |
1490 |
m_currentTracker = m_rootTracker.get(); |
|
5550 |
745 |
m_runState = Executing; |
|
5551 |
} |
||
5552 |
void completeCycle() { |
||
5553 |
1145 |
m_runState = CompletedCycle; |
|
5554 |
} |
||
5555 |
|||
5556 |
bool completedCycle() const { |
||
5557 |
return m_runState == CompletedCycle; |
||
5558 |
} |
||
5559 |
ITracker& currentTracker() { |
||
5560 |
return *m_currentTracker; |
||
5561 |
} |
||
5562 |
void setCurrentTracker( ITracker* tracker ) { |
||
5563 |
2290 |
m_currentTracker = tracker; |
|
5564 |
} |
||
5565 |
}; |
||
5566 |
|||
5567 |
class TrackerBase : public ITracker { |
||
5568 |
protected: |
||
5569 |
enum CycleState { |
||
5570 |
NotStarted, |
||
5571 |
Executing, |
||
5572 |
ExecutingChildren, |
||
5573 |
NeedsAnotherRun, |
||
5574 |
CompletedSuccessfully, |
||
5575 |
Failed |
||
5576 |
}; |
||
5577 |
162270 |
class TrackerHasName { |
|
5578 |
std::string m_name; |
||
5579 |
public: |
||
5580 |
18030 |
TrackerHasName( std::string const& name ) : m_name( name ) {} |
|
5581 |
192758 |
bool operator ()( Ptr<ITracker> const& tracker ) { |
|
5582 |
578274 |
return tracker->name() == m_name; |
|
5583 |
} |
||
5584 |
}; |
||
5585 |
typedef std::vector<Ptr<ITracker> > Children; |
||
5586 |
std::string m_name; |
||
5587 |
TrackerContext& m_ctx; |
||
5588 |
ITracker* m_parent; |
||
5589 |
Children m_children; |
||
5590 |
CycleState m_runState; |
||
5591 |
public: |
||
5592 |
TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) |
||
5593 |
1188 |
: m_name( name ), |
|
5594 |
m_ctx( ctx ), |
||
5595 |
m_parent( parent ), |
||
5596 |
4752 |
m_runState( NotStarted ) |
|
5597 |
{} |
||
5598 |
virtual ~TrackerBase(); |
||
5599 |
|||
5600 |
192758 |
virtual std::string name() const CATCH_OVERRIDE { |
|
5601 |
385516 |
return m_name; |
|
5602 |
} |
||
5603 |
9815 |
virtual bool isComplete() const CATCH_OVERRIDE { |
|
5604 |
9815 |
return m_runState == CompletedSuccessfully || m_runState == Failed; |
|
5605 |
} |
||
5606 |
745 |
virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { |
|
5607 |
745 |
return m_runState == CompletedSuccessfully; |
|
5608 |
} |
||
5609 |
8270 |
virtual bool isOpen() const CATCH_OVERRIDE { |
|
5610 |
✓✓✓✓ |
8270 |
return m_runState != NotStarted && !isComplete(); |
5611 |
} |
||
5612 |
virtual bool hasChildren() const CATCH_OVERRIDE { |
||
5613 |
return !m_children.empty(); |
||
5614 |
} |
||
5615 |
|||
5616 |
794 |
virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE { |
|
5617 |
794 |
m_children.push_back( child ); |
|
5618 |
794 |
} |
|
5619 |
|||
5620 |
9015 |
virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { |
|
5621 |
✓✗ | 45075 |
Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); |
5622 |
27045 |
return( it != m_children.end() ) |
|
5623 |
✓✓ | 17236 |
? it->get() |
5624 |
9015 |
: CATCH_NULL; |
|
5625 |
} |
||
5626 |
virtual ITracker& parent() CATCH_OVERRIDE { |
||
5627 |
assert( m_parent ); // Should always be non-null except for root |
||
5628 |
return *m_parent; |
||
5629 |
} |
||
5630 |
|||
5631 |
1545 |
virtual void openChild() CATCH_OVERRIDE { |
|
5632 |
✓✓ | 1545 |
if( m_runState != ExecutingChildren ) { |
5633 |
794 |
m_runState = ExecutingChildren; |
|
5634 |
✓✓ | 794 |
if( m_parent ) |
5635 |
400 |
m_parent->openChild(); |
|
5636 |
} |
||
5637 |
1545 |
} |
|
5638 |
|||
5639 |
virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } |
||
5640 |
virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } |
||
5641 |
|||
5642 |
void open() { |
||
5643 |
1145 |
m_runState = Executing; |
|
5644 |
1145 |
moveToThis(); |
|
5645 |
✓✗ | 1145 |
if( m_parent ) |
5646 |
1145 |
m_parent->openChild(); |
|
5647 |
} |
||
5648 |
|||
5649 |
1145 |
virtual void close() CATCH_OVERRIDE { |
|
5650 |
|||
5651 |
// Close any still open children (e.g. generators) |
||
5652 |
✗✓ | 1145 |
while( &m_ctx.currentTracker() != this ) |
5653 |
m_ctx.currentTracker().close(); |
||
5654 |
|||
5655 |
✗✓✓✗ ✗ |
1145 |
switch( m_runState ) { |
5656 |
case NotStarted: |
||
5657 |
case CompletedSuccessfully: |
||
5658 |
case Failed: |
||
5659 |
throw std::logic_error( "Illogical state" ); |
||
5660 |
|||
5661 |
case NeedsAnotherRun: |
||
5662 |
break;; |
||
5663 |
|||
5664 |
case Executing: |
||
5665 |
745 |
m_runState = CompletedSuccessfully; |
|
5666 |
745 |
break; |
|
5667 |
case ExecutingChildren: |
||
5668 |
✓✗✓✓ ✓✓ |
1600 |
if( m_children.empty() || m_children.back()->isComplete() ) |
5669 |
49 |
m_runState = CompletedSuccessfully; |
|
5670 |
break; |
||
5671 |
|||
5672 |
default: |
||
5673 |
throw std::logic_error( "Unexpected state" ); |
||
5674 |
} |
||
5675 |
1145 |
moveToParent(); |
|
5676 |
1145 |
m_ctx.completeCycle(); |
|
5677 |
1145 |
} |
|
5678 |
virtual void fail() CATCH_OVERRIDE { |
||
5679 |
m_runState = Failed; |
||
5680 |
if( m_parent ) |
||
5681 |
m_parent->markAsNeedingAnotherRun(); |
||
5682 |
moveToParent(); |
||
5683 |
m_ctx.completeCycle(); |
||
5684 |
} |
||
5685 |
virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { |
||
5686 |
m_runState = NeedsAnotherRun; |
||
5687 |
} |
||
5688 |
private: |
||
5689 |
void moveToParent() { |
||
5690 |
✗✗✗✓ |
1145 |
assert( m_parent ); |
5691 |
2290 |
m_ctx.setCurrentTracker( m_parent ); |
|
5692 |
} |
||
5693 |
void moveToThis() { |
||
5694 |
2290 |
m_ctx.setCurrentTracker( this ); |
|
5695 |
} |
||
5696 |
}; |
||
5697 |
|||
5698 |
class SectionTracker : public TrackerBase { |
||
5699 |
public: |
||
5700 |
SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) |
||
5701 |
2376 |
: TrackerBase( name, ctx, parent ) |
|
5702 |
{} |
||
5703 |
virtual ~SectionTracker(); |
||
5704 |
|||
5705 |
8221 |
virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } |
|
5706 |
|||
5707 |
9015 |
static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { |
|
5708 |
9015 |
SectionTracker* section = CATCH_NULL; |
|
5709 |
|||
5710 |
9015 |
ITracker& currentTracker = ctx.currentTracker(); |
|
5711 |
✓✓ | 9015 |
if( ITracker* childTracker = currentTracker.findChild( name ) ) { |
5712 |
assert( childTracker ); |
||
5713 |
✗✓ | 8221 |
assert( childTracker->isSectionTracker() ); |
5714 |
section = static_cast<SectionTracker*>( childTracker ); |
||
5715 |
} |
||
5716 |
else { |
||
5717 |
1588 |
section = new SectionTracker( name, ctx, ¤tTracker ); |
|
5718 |
✓✗ | 2382 |
currentTracker.addChild( section ); |
5719 |
} |
||
5720 |
✓✓✓✓ ✓✓ |
9015 |
if( !ctx.completedCycle() && !section->isComplete() ) { |
5721 |
|||
5722 |
1145 |
section->open(); |
|
5723 |
} |
||
5724 |
9015 |
return *section; |
|
5725 |
} |
||
5726 |
}; |
||
5727 |
|||
5728 |
class IndexTracker : public TrackerBase { |
||
5729 |
int m_size; |
||
5730 |
int m_index; |
||
5731 |
public: |
||
5732 |
IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) |
||
5733 |
: TrackerBase( name, ctx, parent ), |
||
5734 |
m_size( size ), |
||
5735 |
m_index( -1 ) |
||
5736 |
{} |
||
5737 |
virtual ~IndexTracker(); |
||
5738 |
|||
5739 |
virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } |
||
5740 |
|||
5741 |
static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { |
||
5742 |
IndexTracker* tracker = CATCH_NULL; |
||
5743 |
|||
5744 |
ITracker& currentTracker = ctx.currentTracker(); |
||
5745 |
if( ITracker* childTracker = currentTracker.findChild( name ) ) { |
||
5746 |
assert( childTracker ); |
||
5747 |
assert( childTracker->isIndexTracker() ); |
||
5748 |
tracker = static_cast<IndexTracker*>( childTracker ); |
||
5749 |
} |
||
5750 |
else { |
||
5751 |
tracker = new IndexTracker( name, ctx, ¤tTracker, size ); |
||
5752 |
currentTracker.addChild( tracker ); |
||
5753 |
} |
||
5754 |
|||
5755 |
if( !ctx.completedCycle() && !tracker->isComplete() ) { |
||
5756 |
if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) |
||
5757 |
tracker->moveNext(); |
||
5758 |
tracker->open(); |
||
5759 |
} |
||
5760 |
|||
5761 |
return *tracker; |
||
5762 |
} |
||
5763 |
|||
5764 |
int index() const { return m_index; } |
||
5765 |
|||
5766 |
void moveNext() { |
||
5767 |
m_index++; |
||
5768 |
m_children.clear(); |
||
5769 |
} |
||
5770 |
|||
5771 |
virtual void close() CATCH_OVERRIDE { |
||
5772 |
TrackerBase::close(); |
||
5773 |
if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) |
||
5774 |
m_runState = Executing; |
||
5775 |
} |
||
5776 |
}; |
||
5777 |
|||
5778 |
394 |
inline ITracker& TrackerContext::startRun() { |
|
5779 |
✓✗ | 2364 |
m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); |
5780 |
394 |
m_currentTracker = CATCH_NULL; |
|
5781 |
394 |
m_runState = Executing; |
|
5782 |
788 |
return *m_rootTracker; |
|
5783 |
} |
||
5784 |
|||
5785 |
} // namespace TestCaseTracking |
||
5786 |
|||
5787 |
using TestCaseTracking::ITracker; |
||
5788 |
using TestCaseTracking::TrackerContext; |
||
5789 |
using TestCaseTracking::SectionTracker; |
||
5790 |
using TestCaseTracking::IndexTracker; |
||
5791 |
|||
5792 |
} // namespace Catch |
||
5793 |
|||
5794 |
// #included from: catch_fatal_condition.hpp |
||
5795 |
#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED |
||
5796 |
|||
5797 |
namespace Catch { |
||
5798 |
|||
5799 |
// Report the error condition then exit the process |
||
5800 |
inline void fatal( std::string const& message, int exitCode ) { |
||
5801 |
IContext& context = Catch::getCurrentContext(); |
||
5802 |
IResultCapture* resultCapture = context.getResultCapture(); |
||
5803 |
resultCapture->handleFatalErrorCondition( message ); |
||
5804 |
|||
5805 |
if( Catch::alwaysTrue() ) // avoids "no return" warnings |
||
5806 |
exit( exitCode ); |
||
5807 |
} |
||
5808 |
|||
5809 |
} // namespace Catch |
||
5810 |
|||
5811 |
#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// |
||
5812 |
|||
5813 |
namespace Catch { |
||
5814 |
|||
5815 |
struct FatalConditionHandler { |
||
5816 |
void reset() {} |
||
5817 |
}; |
||
5818 |
|||
5819 |
} // namespace Catch |
||
5820 |
|||
5821 |
#else // Not Windows - assumed to be POSIX compatible ////////////////////////// |
||
5822 |
|||
5823 |
#include <signal.h> |
||
5824 |
|||
5825 |
namespace Catch { |
||
5826 |
|||
5827 |
struct SignalDefs { int id; const char* name; }; |
||
5828 |
extern SignalDefs signalDefs[]; |
||
5829 |
SignalDefs signalDefs[] = { |
||
5830 |
{ SIGINT, "SIGINT - Terminal interrupt signal" }, |
||
5831 |
{ SIGILL, "SIGILL - Illegal instruction signal" }, |
||
5832 |
{ SIGFPE, "SIGFPE - Floating point error signal" }, |
||
5833 |
{ SIGSEGV, "SIGSEGV - Segmentation violation signal" }, |
||
5834 |
{ SIGTERM, "SIGTERM - Termination request signal" }, |
||
5835 |
{ SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } |
||
5836 |
}; |
||
5837 |
|||
5838 |
struct FatalConditionHandler { |
||
5839 |
|||
5840 |
static void handleSignal( int sig ) { |
||
5841 |
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) |
||
5842 |
if( sig == signalDefs[i].id ) |
||
5843 |
fatal( signalDefs[i].name, -sig ); |
||
5844 |
fatal( "<unknown signal>", -sig ); |
||
5845 |
} |
||
5846 |
|||
5847 |
745 |
FatalConditionHandler() : m_isSet( true ) { |
|
5848 |
✓✓ | 5215 |
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) |
5849 |
4470 |
signal( signalDefs[i].id, handleSignal ); |
|
5850 |
} |
||
5851 |
~FatalConditionHandler() { |
||
5852 |
745 |
reset(); |
|
5853 |
} |
||
5854 |
1490 |
void reset() { |
|
5855 |
✓✓ | 1490 |
if( m_isSet ) { |
5856 |
✓✓ | 9685 |
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) |
5857 |
4470 |
signal( signalDefs[i].id, SIG_DFL ); |
|
5858 |
745 |
m_isSet = false; |
|
5859 |
} |
||
5860 |
1490 |
} |
|
5861 |
|||
5862 |
bool m_isSet; |
||
5863 |
}; |
||
5864 |
|||
5865 |
} // namespace Catch |
||
5866 |
|||
5867 |
#endif // not Windows |
||
5868 |
|||
5869 |
#include <set> |
||
5870 |
#include <string> |
||
5871 |
|||
5872 |
namespace Catch { |
||
5873 |
|||
5874 |
class StreamRedirect { |
||
5875 |
|||
5876 |
public: |
||
5877 |
StreamRedirect( std::ostream& stream, std::string& targetString ) |
||
5878 |
: m_stream( stream ), |
||
5879 |
m_prevBuf( stream.rdbuf() ), |
||
5880 |
m_targetString( targetString ) |
||
5881 |
{ |
||
5882 |
stream.rdbuf( m_oss.rdbuf() ); |
||
5883 |
} |
||
5884 |
|||
5885 |
~StreamRedirect() { |
||
5886 |
m_targetString += m_oss.str(); |
||
5887 |
m_stream.rdbuf( m_prevBuf ); |
||
5888 |
} |
||
5889 |
|||
5890 |
private: |
||
5891 |
std::ostream& m_stream; |
||
5892 |
std::streambuf* m_prevBuf; |
||
5893 |
std::ostringstream m_oss; |
||
5894 |
std::string& m_targetString; |
||
5895 |
}; |
||
5896 |
|||
5897 |
/////////////////////////////////////////////////////////////////////////// |
||
5898 |
|||
5899 |
class RunContext : public IResultCapture, public IRunner { |
||
5900 |
|||
5901 |
RunContext( RunContext const& ); |
||
5902 |
void operator =( RunContext const& ); |
||
5903 |
|||
5904 |
public: |
||
5905 |
|||
5906 |
1 |
explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter ) |
|
5907 |
✓✗ | 3 |
: m_runInfo( _config->name() ), |
5908 |
✓✗ | 1 |
m_context( getCurrentMutableContext() ), |
5909 |
m_activeTestCase( CATCH_NULL ), |
||
5910 |
m_config( _config ), |
||
5911 |
13 |
m_reporter( reporter ) |
|
5912 |
{ |
||
5913 |
✓✗ | 1 |
m_context.setRunner( this ); |
5914 |
✓✗ | 1 |
m_context.setConfig( m_config ); |
5915 |
✓✗ | 1 |
m_context.setResultCapture( this ); |
5916 |
✓✗ | 2 |
m_reporter->testRunStarting( m_runInfo ); |
5917 |
1 |
} |
|
5918 |
|||
5919 |
8 |
virtual ~RunContext() { |
|
5920 |
5 |
m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); |
|
5921 |
1 |
} |
|
5922 |
|||
5923 |
1 |
void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { |
|
5924 |
✓✗ | 4 |
m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); |
5925 |
1 |
} |
|
5926 |
1 |
void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { |
|
5927 |
✓✗✓✗ |
5 |
m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); |
5928 |
1 |
} |
|
5929 |
|||
5930 |
394 |
Totals runTest( TestCase const& testCase ) { |
|
5931 |
394 |
Totals prevTotals = m_totals; |
|
5932 |
|||
5933 |
788 |
std::string redirectedCout; |
|
5934 |
788 |
std::string redirectedCerr; |
|
5935 |
|||
5936 |
✓✗ | 788 |
TestCaseInfo testInfo = testCase.getTestCaseInfo(); |
5937 |
|||
5938 |
✓✗ | 788 |
m_reporter->testCaseStarting( testInfo ); |
5939 |
|||
5940 |
394 |
m_activeTestCase = &testCase; |
|
5941 |
|||
5942 |
✗✓ | 394 |
do { |
5943 |
✓✗ | 394 |
m_trackerContext.startRun(); |
5944 |
✓✓ | 745 |
do { |
5945 |
1490 |
m_trackerContext.startCycle(); |
|
5946 |
✓✗ | 745 |
m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); |
5947 |
✓✗ | 745 |
runCurrentTest( redirectedCout, redirectedCerr ); |
5948 |
} |
||
5949 |
✓✗✓✓ ✓✗✗✓ |
745 |
while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); |
5950 |
} |
||
5951 |
// !TBD: deprecated - this will be replaced by indexed trackers |
||
5952 |
✓✗✗✓ ✗✗✗✗ |
394 |
while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); |
5953 |
|||
5954 |
394 |
Totals deltaTotals = m_totals.delta( prevTotals ); |
|
5955 |
✗✓✗✗ ✗✓ |
394 |
if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { |
5956 |
deltaTotals.assertions.failed++; |
||
5957 |
deltaTotals.testCases.passed--; |
||
5958 |
deltaTotals.testCases.failed++; |
||
5959 |
} |
||
5960 |
788 |
m_totals.testCases += deltaTotals.testCases; |
|
5961 |
✓✗ | 1576 |
m_reporter->testCaseEnded( TestCaseStats( testInfo, |
5962 |
deltaTotals, |
||
5963 |
redirectedCout, |
||
5964 |
redirectedCerr, |
||
5965 |
✓✗✓✗ |
788 |
aborting() ) ); |
5966 |
|||
5967 |
394 |
m_activeTestCase = CATCH_NULL; |
|
5968 |
394 |
m_testCaseTracker = CATCH_NULL; |
|
5969 |
|||
5970 |
394 |
return deltaTotals; |
|
5971 |
} |
||
5972 |
|||
5973 |
Ptr<IConfig const> config() const { |
||
5974 |
return m_config; |
||
5975 |
} |
||
5976 |
|||
5977 |
private: // IResultCapture |
||
5978 |
|||
5979 |
1432923 |
virtual void assertionEnded( AssertionResult const& result ) { |
|
5980 |
✓✗ | 1432923 |
if( result.getResultType() == ResultWas::Ok ) { |
5981 |
1432923 |
m_totals.assertions.passed++; |
|
5982 |
} |
||
5983 |
else if( !result.isOk() ) { |
||
5984 |
m_totals.assertions.failed++; |
||
5985 |
} |
||
5986 |
|||
5987 |
✓✗✗✓ |
2865846 |
if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) |
5988 |
m_messages.clear(); |
||
5989 |
|||
5990 |
// Reset working state |
||
5991 |
✓✗✓✗ |
10030461 |
m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); |
5992 |
1432923 |
m_lastResult = result; |
|
5993 |
1432923 |
} |
|
5994 |
|||
5995 |
8270 |
virtual bool sectionStarted ( |
|
5996 |
SectionInfo const& sectionInfo, |
||
5997 |
Counts& assertions |
||
5998 |
) |
||
5999 |
{ |
||
6000 |
16540 |
std::ostringstream oss; |
|
6001 |
✓✗ | 24810 |
oss << sectionInfo.name << "@" << sectionInfo.lineInfo; |
6002 |
|||
6003 |
✓✗ | 16540 |
ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); |
6004 |
✓✗✓✓ |
8270 |
if( !sectionTracker.isOpen() ) |
6005 |
return false; |
||
6006 |
800 |
m_activeSections.push_back( §ionTracker ); |
|
6007 |
|||
6008 |
800 |
m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; |
|
6009 |
|||
6010 |
✓✗ | 800 |
m_reporter->sectionStarting( sectionInfo ); |
6011 |
|||
6012 |
400 |
assertions = m_totals.assertions; |
|
6013 |
|||
6014 |
400 |
return true; |
|
6015 |
} |
||
6016 |
1145 |
bool testForMissingAssertions( Counts& assertions ) { |
|
6017 |
✓✓ | 1145 |
if( assertions.total() != 0 ) |
6018 |
return false; |
||
6019 |
✗✓ | 296 |
if( !m_config->warnAboutMissingAssertions() ) |
6020 |
return false; |
||
6021 |
if( m_trackerContext.currentTracker().hasChildren() ) |
||
6022 |
return false; |
||
6023 |
m_totals.assertions.failed++; |
||
6024 |
assertions.failed++; |
||
6025 |
return true; |
||
6026 |
} |
||
6027 |
|||
6028 |
400 |
virtual void sectionEnded( SectionEndInfo const& endInfo ) { |
|
6029 |
800 |
Counts assertions = m_totals.assertions - endInfo.prevAssertions; |
|
6030 |
400 |
bool missingAssertions = testForMissingAssertions( assertions ); |
|
6031 |
|||
6032 |
✓✗ | 800 |
if( !m_activeSections.empty() ) { |
6033 |
800 |
m_activeSections.back()->close(); |
|
6034 |
400 |
m_activeSections.pop_back(); |
|
6035 |
} |
||
6036 |
|||
6037 |
✓✗ | 1600 |
m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); |
6038 |
800 |
m_messages.clear(); |
|
6039 |
400 |
} |
|
6040 |
|||
6041 |
virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { |
||
6042 |
if( m_unfinishedSections.empty() ) |
||
6043 |
m_activeSections.back()->fail(); |
||
6044 |
else |
||
6045 |
m_activeSections.back()->close(); |
||
6046 |
m_activeSections.pop_back(); |
||
6047 |
|||
6048 |
m_unfinishedSections.push_back( endInfo ); |
||
6049 |
} |
||
6050 |
|||
6051 |
virtual void pushScopedMessage( MessageInfo const& message ) { |
||
6052 |
m_messages.push_back( message ); |
||
6053 |
} |
||
6054 |
|||
6055 |
virtual void popScopedMessage( MessageInfo const& message ) { |
||
6056 |
m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); |
||
6057 |
} |
||
6058 |
|||
6059 |
394 |
virtual std::string getCurrentTestName() const { |
|
6060 |
394 |
return m_activeTestCase |
|
6061 |
394 |
? m_activeTestCase->getTestCaseInfo().name |
|
6062 |
✓✗ | 788 |
: ""; |
6063 |
} |
||
6064 |
|||
6065 |
virtual const AssertionResult* getLastResult() const { |
||
6066 |
return &m_lastResult; |
||
6067 |
} |
||
6068 |
|||
6069 |
virtual void handleFatalErrorCondition( std::string const& message ) { |
||
6070 |
ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); |
||
6071 |
resultBuilder.setResultType( ResultWas::FatalErrorCondition ); |
||
6072 |
resultBuilder << message; |
||
6073 |
// stack |
||
6074 |
#ifdef HAVE_EXECINFO |
||
6075 |
{ |
||
6076 |
void *array[15]; |
||
6077 |
const int size = static_cast<int>(backtrace(array, 15)); |
||
6078 |
char **strings = backtrace_symbols(array, size); |
||
6079 |
for (int i = 0; i < size; i++) |
||
6080 |
resultBuilder << strings[i]; |
||
6081 |
free(strings); |
||
6082 |
} |
||
6083 |
#endif // HAVE_EXECINFO |
||
6084 |
// stack |
||
6085 |
|||
6086 |
resultBuilder.captureExpression(); |
||
6087 |
|||
6088 |
handleUnfinishedSections(); |
||
6089 |
|||
6090 |
// Recreate section for test case (as we will lose the one that was in scope) |
||
6091 |
TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); |
||
6092 |
SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); |
||
6093 |
|||
6094 |
Counts assertions; |
||
6095 |
assertions.failed = 1; |
||
6096 |
SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); |
||
6097 |
m_reporter->sectionEnded( testCaseSectionStats ); |
||
6098 |
|||
6099 |
TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); |
||
6100 |
|||
6101 |
Totals deltaTotals; |
||
6102 |
deltaTotals.testCases.failed = 1; |
||
6103 |
m_reporter->testCaseEnded( TestCaseStats( testInfo, |
||
6104 |
deltaTotals, |
||
6105 |
"", |
||
6106 |
"", |
||
6107 |
false ) ); |
||
6108 |
m_totals.testCases.failed++; |
||
6109 |
testGroupEnded( "", m_totals, 1, 1 ); |
||
6110 |
m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); |
||
6111 |
} |
||
6112 |
|||
6113 |
public: |
||
6114 |
// !TBD We need to do this another way! |
||
6115 |
746 |
bool aborting() const { |
|
6116 |
✓✗ | 2282 |
return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() ); |
6117 |
} |
||
6118 |
|||
6119 |
private: |
||
6120 |
|||
6121 |
745 |
void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { |
|
6122 |
1490 |
TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); |
|
6123 |
1490 |
SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); |
|
6124 |
✓✗ | 1490 |
m_reporter->sectionStarting( testCaseSection ); |
6125 |
745 |
Counts prevAssertions = m_totals.assertions; |
|
6126 |
745 |
double duration = 0; |
|
6127 |
try { |
||
6128 |
✓✗✓✗ ✓✗ |
5215 |
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); |
6129 |
|||
6130 |
✓✗ | 1490 |
seedRng( *m_config ); |
6131 |
|||
6132 |
745 |
Timer timer; |
|
6133 |
745 |
timer.start(); |
|
6134 |
✓✗✗✓ |
1490 |
if( m_reporter->getPreferences().shouldRedirectStdOut ) { |
6135 |
StreamRedirect coutRedir( Catch::cout(), redirectedCout ); |
||
6136 |
StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); |
||
6137 |
invokeActiveTestCase(); |
||
6138 |
} |
||
6139 |
else { |
||
6140 |
✓✗ | 745 |
invokeActiveTestCase(); |
6141 |
} |
||
6142 |
745 |
duration = timer.getElapsedSeconds(); |
|
6143 |
} |
||
6144 |
catch( TestFailureException& ) { |
||
6145 |
// This just means the test was aborted due to failure |
||
6146 |
} |
||
6147 |
catch(...) { |
||
6148 |
makeUnexpectedResultBuilder().useActiveException(); |
||
6149 |
} |
||
6150 |
✓✗ | 745 |
m_testCaseTracker->close(); |
6151 |
✓✗ | 745 |
handleUnfinishedSections(); |
6152 |
1490 |
m_messages.clear(); |
|
6153 |
|||
6154 |
1490 |
Counts assertions = m_totals.assertions - prevAssertions; |
|
6155 |
✓✗ | 745 |
bool missingAssertions = testForMissingAssertions( assertions ); |
6156 |
|||
6157 |
✗✓ | 745 |
if( testCaseInfo.okToFail() ) { |
6158 |
std::swap( assertions.failedButOk, assertions.failed ); |
||
6159 |
m_totals.assertions.failed -= assertions.failedButOk; |
||
6160 |
m_totals.assertions.failedButOk += assertions.failedButOk; |
||
6161 |
} |
||
6162 |
|||
6163 |
2235 |
SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); |
|
6164 |
✓✗ | 1490 |
m_reporter->sectionEnded( testCaseSectionStats ); |
6165 |
745 |
} |
|
6166 |
|||
6167 |
745 |
void invokeActiveTestCase() { |
|
6168 |
1490 |
FatalConditionHandler fatalConditionHandler; // Handle signals |
|
6169 |
1490 |
m_activeTestCase->invoke(); |
|
6170 |
745 |
fatalConditionHandler.reset(); |
|
6171 |
745 |
} |
|
6172 |
|||
6173 |
private: |
||
6174 |
|||
6175 |
ResultBuilder makeUnexpectedResultBuilder() const { |
||
6176 |
return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), |
||
6177 |
m_lastAssertionInfo.lineInfo, |
||
6178 |
m_lastAssertionInfo.capturedExpression.c_str(), |
||
6179 |
m_lastAssertionInfo.resultDisposition ); |
||
6180 |
} |
||
6181 |
|||
6182 |
745 |
void handleUnfinishedSections() { |
|
6183 |
// If sections ended prematurely due to an exception we stored their |
||
6184 |
// infos here so we can tear them down outside the unwind process. |
||
6185 |
✗✓ | 2980 |
for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(), |
6186 |
2235 |
itEnd = m_unfinishedSections.rend(); |
|
6187 |
it != itEnd; |
||
6188 |
++it ) |
||
6189 |
sectionEnded( *it ); |
||
6190 |
1490 |
m_unfinishedSections.clear(); |
|
6191 |
745 |
} |
|
6192 |
|||
6193 |
TestRunInfo m_runInfo; |
||
6194 |
IMutableContext& m_context; |
||
6195 |
TestCase const* m_activeTestCase; |
||
6196 |
ITracker* m_testCaseTracker; |
||
6197 |
ITracker* m_currentSectionTracker; |
||
6198 |
AssertionResult m_lastResult; |
||
6199 |
|||
6200 |
Ptr<IConfig const> m_config; |
||
6201 |
Totals m_totals; |
||
6202 |
Ptr<IStreamingReporter> m_reporter; |
||
6203 |
std::vector<MessageInfo> m_messages; |
||
6204 |
AssertionInfo m_lastAssertionInfo; |
||
6205 |
std::vector<SectionEndInfo> m_unfinishedSections; |
||
6206 |
std::vector<ITracker*> m_activeSections; |
||
6207 |
TrackerContext m_trackerContext; |
||
6208 |
}; |
||
6209 |
|||
6210 |
1441593 |
IResultCapture& getResultCapture() { |
|
6211 |
✓✗ | 1441593 |
if( IResultCapture* capture = getCurrentContext().getResultCapture() ) |
6212 |
1441593 |
return *capture; |
|
6213 |
else |
||
6214 |
throw std::logic_error( "No result capture instance" ); |
||
6215 |
} |
||
6216 |
|||
6217 |
} // end namespace Catch |
||
6218 |
|||
6219 |
// #included from: internal/catch_version.h |
||
6220 |
#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED |
||
6221 |
|||
6222 |
namespace Catch { |
||
6223 |
|||
6224 |
// Versioning information |
||
6225 |
2 |
struct Version { |
|
6226 |
Version( unsigned int _majorVersion, |
||
6227 |
unsigned int _minorVersion, |
||
6228 |
unsigned int _patchNumber, |
||
6229 |
std::string const& _branchName, |
||
6230 |
unsigned int _buildNumber ); |
||
6231 |
|||
6232 |
unsigned int const majorVersion; |
||
6233 |
unsigned int const minorVersion; |
||
6234 |
unsigned int const patchNumber; |
||
6235 |
|||
6236 |
// buildNumber is only used if branchName is not null |
||
6237 |
std::string const branchName; |
||
6238 |
unsigned int const buildNumber; |
||
6239 |
|||
6240 |
friend std::ostream& operator << ( std::ostream& os, Version const& version ); |
||
6241 |
|||
6242 |
private: |
||
6243 |
void operator=( Version const& ); |
||
6244 |
}; |
||
6245 |
|||
6246 |
extern Version libraryVersion; |
||
6247 |
} |
||
6248 |
|||
6249 |
#include <fstream> |
||
6250 |
#include <stdlib.h> |
||
6251 |
#include <limits> |
||
6252 |
|||
6253 |
namespace Catch { |
||
6254 |
|||
6255 |
1 |
Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) { |
|
6256 |
✓✗ | 5 |
Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); |
6257 |
✗✓ | 1 |
if( !reporter ) { |
6258 |
std::ostringstream oss; |
||
6259 |
oss << "No reporter registered with name: '" << reporterName << "'"; |
||
6260 |
throw std::domain_error( oss.str() ); |
||
6261 |
} |
||
6262 |
1 |
return reporter; |
|
6263 |
} |
||
6264 |
|||
6265 |
1 |
Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) { |
|
6266 |
3 |
std::vector<std::string> reporters = config->getReporterNames(); |
|
6267 |
✓✗ | 1 |
if( reporters.empty() ) |
6268 |
✓✗ | 5 |
reporters.push_back( "console" ); |
6269 |
|||
6270 |
1 |
Ptr<IStreamingReporter> reporter; |
|
6271 |
✓✓ | 6 |
for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end(); |
6272 |
it != itEnd; |
||
6273 |
++it ) |
||
6274 |
✓✗✓✗ ✓✗ |
3 |
reporter = addReporter( reporter, createReporter( *it, config ) ); |
6275 |
1 |
return reporter; |
|
6276 |
} |
||
6277 |
1 |
Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) { |
|
6278 |
2 |
IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); |
|
6279 |
✗✓ | 5 |
for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); |
6280 |
it != itEnd; |
||
6281 |
++it ) |
||
6282 |
reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); |
||
6283 |
2 |
return reporters; |
|
6284 |
} |
||
6285 |
|||
6286 |
1 |
Totals runTests( Ptr<Config> const& config ) { |
|
6287 |
|||
6288 |
3 |
Ptr<IConfig const> iconfig = config.get(); |
|
6289 |
|||
6290 |
✓✗ | 2 |
Ptr<IStreamingReporter> reporter = makeReporter( config ); |
6291 |
✓✗✓✗ |
3 |
reporter = addListeners( iconfig, reporter ); |
6292 |
|||
6293 |
✓✗ | 2 |
RunContext context( iconfig, reporter ); |
6294 |
|||
6295 |
1 |
Totals totals; |
|
6296 |
|||
6297 |
✓✗✓✗ |
2 |
context.testGroupStarting( config->name(), 1, 1 ); |
6298 |
|||
6299 |
✓✗ | 3 |
TestSpec testSpec = config->testSpec(); |
6300 |
✓✗ | 1 |
if( !testSpec.hasFilters() ) |
6301 |
✓✗✓✗ |
9 |
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests |
6302 |
|||
6303 |
✓✗ | 1 |
std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig ); |
6304 |
✓✓ | 398 |
for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); |
6305 |
it != itEnd; |
||
6306 |
++it ) { |
||
6307 |
✓✗✓✗ ✗✓✓✗ |
788 |
if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) |
6308 |
✓✗ | 788 |
totals += context.runTest( *it ); |
6309 |
else |
||
6310 |
reporter->skipTest( *it ); |
||
6311 |
} |
||
6312 |
|||
6313 |
✓✗✓✗ |
2 |
context.testGroupEnded( iconfig->name(), totals, 1, 1 ); |
6314 |
1 |
return totals; |
|
6315 |
} |
||
6316 |
|||
6317 |
void applyFilenamesAsTags( IConfig const& config ) { |
||
6318 |
std::vector<TestCase> const& tests = getAllTestCasesSorted( config ); |
||
6319 |
for(std::size_t i = 0; i < tests.size(); ++i ) { |
||
6320 |
TestCase& test = const_cast<TestCase&>( tests[i] ); |
||
6321 |
std::set<std::string> tags = test.tags; |
||
6322 |
|||
6323 |
std::string filename = test.lineInfo.file; |
||
6324 |
std::string::size_type lastSlash = filename.find_last_of( "\\/" ); |
||
6325 |
if( lastSlash != std::string::npos ) |
||
6326 |
filename = filename.substr( lastSlash+1 ); |
||
6327 |
|||
6328 |
std::string::size_type lastDot = filename.find_last_of( "." ); |
||
6329 |
if( lastDot != std::string::npos ) |
||
6330 |
filename = filename.substr( 0, lastDot ); |
||
6331 |
|||
6332 |
tags.insert( "#" + filename ); |
||
6333 |
setTags( test, tags ); |
||
6334 |
} |
||
6335 |
} |
||
6336 |
|||
6337 |
class Session : NonCopyable { |
||
6338 |
static bool alreadyInstantiated; |
||
6339 |
|||
6340 |
public: |
||
6341 |
|||
6342 |
struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; |
||
6343 |
|||
6344 |
1 |
Session() |
|
6345 |
5 |
: m_cli( makeCommandLineParser() ) { |
|
6346 |
✗✓ | 1 |
if( alreadyInstantiated ) { |
6347 |
std::string msg = "Only one instance of Catch::Session can ever be used"; |
||
6348 |
Catch::cerr() << msg << std::endl; |
||
6349 |
throw std::logic_error( msg ); |
||
6350 |
} |
||
6351 |
1 |
alreadyInstantiated = true; |
|
6352 |
1 |
} |
|
6353 |
3 |
~Session() { |
|
6354 |
1 |
Catch::cleanUp(); |
|
6355 |
1 |
} |
|
6356 |
|||
6357 |
void showHelp( std::string const& processName ) { |
||
6358 |
Catch::cout() << "\nCatch v" << libraryVersion << "\n"; |
||
6359 |
|||
6360 |
m_cli.usage( Catch::cout(), processName ); |
||
6361 |
Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; |
||
6362 |
} |
||
6363 |
|||
6364 |
1 |
int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { |
|
6365 |
try { |
||
6366 |
2 |
m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); |
|
6367 |
✓✗✓✗ ✗✗ |
2 |
m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); |
6368 |
✗✓ | 1 |
if( m_configData.showHelp ) |
6369 |
showHelp( m_configData.processName ); |
||
6370 |
2 |
m_config.reset(); |
|
6371 |
} |
||
6372 |
catch( std::exception& ex ) { |
||
6373 |
{ |
||
6374 |
Colour colourGuard( Colour::Red ); |
||
6375 |
Catch::cerr() |
||
6376 |
<< "\nError(s) in input:\n" |
||
6377 |
<< Text( ex.what(), TextAttributes().setIndent(2) ) |
||
6378 |
<< "\n\n"; |
||
6379 |
} |
||
6380 |
m_cli.usage( Catch::cout(), m_configData.processName ); |
||
6381 |
return (std::numeric_limits<int>::max)(); |
||
6382 |
} |
||
6383 |
1 |
return 0; |
|
6384 |
} |
||
6385 |
|||
6386 |
void useConfigData( ConfigData const& _configData ) { |
||
6387 |
m_configData = _configData; |
||
6388 |
m_config.reset(); |
||
6389 |
} |
||
6390 |
|||
6391 |
1 |
int run( int argc, char const* const* const argv ) { |
|
6392 |
|||
6393 |
1 |
int returnCode = applyCommandLine( argc, argv ); |
|
6394 |
✓✗ | 1 |
if( returnCode == 0 ) |
6395 |
1 |
returnCode = run(); |
|
6396 |
1 |
return returnCode; |
|
6397 |
} |
||
6398 |
|||
6399 |
1 |
int run() { |
|
6400 |
✓✗ | 1 |
if( m_configData.showHelp ) |
6401 |
return 0; |
||
6402 |
|||
6403 |
try |
||
6404 |
{ |
||
6405 |
✓✗ | 1 |
config(); // Force config to be constructed |
6406 |
|||
6407 |
✓✗ | 2 |
seedRng( *m_config ); |
6408 |
|||
6409 |
✗✓ | 1 |
if( m_configData.filenamesAsTags ) |
6410 |
applyFilenamesAsTags( *m_config ); |
||
6411 |
|||
6412 |
// Handle list request |
||
6413 |
✓✗✓✗ ✗✓ |
3 |
if( Option<std::size_t> listed = list( config() ) ) |
6414 |
return static_cast<int>( *listed ); |
||
6415 |
|||
6416 |
✓✗✗✗ |
1 |
return static_cast<int>( runTests( m_config ).assertions.failed ); |
6417 |
} |
||
6418 |
catch( std::exception& ex ) { |
||
6419 |
Catch::cerr() << ex.what() << std::endl; |
||
6420 |
return (std::numeric_limits<int>::max)(); |
||
6421 |
} |
||
6422 |
} |
||
6423 |
|||
6424 |
Clara::CommandLine<ConfigData> const& cli() const { |
||
6425 |
return m_cli; |
||
6426 |
} |
||
6427 |
std::vector<Clara::Parser::Token> const& unusedTokens() const { |
||
6428 |
return m_unusedTokens; |
||
6429 |
} |
||
6430 |
ConfigData& configData() { |
||
6431 |
return m_configData; |
||
6432 |
} |
||
6433 |
2 |
Config& config() { |
|
6434 |
✓✓ | 4 |
if( !m_config ) |
6435 |
✓✗ | 1 |
m_config = new Config( m_configData ); |
6436 |
4 |
return *m_config; |
|
6437 |
} |
||
6438 |
private: |
||
6439 |
Clara::CommandLine<ConfigData> m_cli; |
||
6440 |
std::vector<Clara::Parser::Token> m_unusedTokens; |
||
6441 |
ConfigData m_configData; |
||
6442 |
Ptr<Config> m_config; |
||
6443 |
}; |
||
6444 |
|||
6445 |
bool Session::alreadyInstantiated = false; |
||
6446 |
|||
6447 |
} // end namespace Catch |
||
6448 |
|||
6449 |
// #included from: catch_registry_hub.hpp |
||
6450 |
#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED |
||
6451 |
|||
6452 |
// #included from: catch_test_case_registry_impl.hpp |
||
6453 |
#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED |
||
6454 |
|||
6455 |
#include <vector> |
||
6456 |
#include <set> |
||
6457 |
#include <sstream> |
||
6458 |
#include <iostream> |
||
6459 |
#include <algorithm> |
||
6460 |
|||
6461 |
namespace Catch { |
||
6462 |
|||
6463 |
struct LexSort { |
||
6464 |
bool operator() (TestCase i,TestCase j) const { return (i<j);} |
||
6465 |
}; |
||
6466 |
struct RandomNumberGenerator { |
||
6467 |
int operator()( int n ) const { return std::rand() % n; } |
||
6468 |
}; |
||
6469 |
|||
6470 |
1 |
inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { |
|
6471 |
|||
6472 |
1 |
std::vector<TestCase> sorted = unsortedTestCases; |
|
6473 |
|||
6474 |
✓✗✗✗ ✓ |
1 |
switch( config.runOrder() ) { |
6475 |
case RunTests::InLexicographicalOrder: |
||
6476 |
std::sort( sorted.begin(), sorted.end(), LexSort() ); |
||
6477 |
break; |
||
6478 |
case RunTests::InRandomOrder: |
||
6479 |
{ |
||
6480 |
seedRng( config ); |
||
6481 |
|||
6482 |
RandomNumberGenerator rng; |
||
6483 |
std::random_shuffle( sorted.begin(), sorted.end(), rng ); |
||
6484 |
} |
||
6485 |
break; |
||
6486 |
case RunTests::InDeclarationOrder: |
||
6487 |
// already in declaration order |
||
6488 |
break; |
||
6489 |
} |
||
6490 |
1 |
return sorted; |
|
6491 |
} |
||
6492 |
394 |
bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { |
|
6493 |
✓✗✗✓ ✗✗ |
394 |
return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); |
6494 |
} |
||
6495 |
|||
6496 |
1 |
void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { |
|
6497 |
2 |
std::set<TestCase> seenFunctions; |
|
6498 |
✓✓ | 398 |
for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end(); |
6499 |
it != itEnd; |
||
6500 |
++it ) { |
||
6501 |
788 |
std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it ); |
|
6502 |
✗✓ | 394 |
if( !prev.second ){ |
6503 |
Catch::cerr() |
||
6504 |
<< Colour( Colour::Red ) |
||
6505 |
<< "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" |
||
6506 |
<< "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" |
||
6507 |
<< "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; |
||
6508 |
exit(1); |
||
6509 |
} |
||
6510 |
} |
||
6511 |
1 |
} |
|
6512 |
|||
6513 |
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { |
||
6514 |
std::vector<TestCase> filtered; |
||
6515 |
filtered.reserve( testCases.size() ); |
||
6516 |
for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end(); |
||
6517 |
it != itEnd; |
||
6518 |
++it ) |
||
6519 |
if( matchTest( *it, testSpec, config ) ) |
||
6520 |
filtered.push_back( *it ); |
||
6521 |
return filtered; |
||
6522 |
} |
||
6523 |
1 |
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { |
|
6524 |
1 |
return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); |
|
6525 |
} |
||
6526 |
|||
6527 |
class TestRegistry : public ITestCaseRegistry { |
||
6528 |
public: |
||
6529 |
1 |
TestRegistry() |
|
6530 |
1 |
: m_currentSortOrder( RunTests::InDeclarationOrder ), |
|
6531 |
✓✗ | 3 |
m_unnamedCount( 0 ) |
6532 |
1 |
{} |
|
6533 |
virtual ~TestRegistry(); |
||
6534 |
|||
6535 |
394 |
virtual void registerTest( TestCase const& testCase ) { |
|
6536 |
1182 |
std::string name = testCase.getTestCaseInfo().name; |
|
6537 |
✗✓ | 394 |
if( name == "" ) { |
6538 |
std::ostringstream oss; |
||
6539 |
oss << "Anonymous test case " << ++m_unnamedCount; |
||
6540 |
return registerTest( testCase.withName( oss.str() ) ); |
||
6541 |
} |
||
6542 |
✓✗ | 394 |
m_functions.push_back( testCase ); |
6543 |
} |
||
6544 |
|||
6545 |
virtual std::vector<TestCase> const& getAllTests() const { |
||
6546 |
return m_functions; |
||
6547 |
} |
||
6548 |
1 |
virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const { |
|
6549 |
✓✗ | 2 |
if( m_sortedFunctions.empty() ) |
6550 |
1 |
enforceNoDuplicateTestCases( m_functions ); |
|
6551 |
|||
6552 |
✓✗✓✗ ✓✗ |
2 |
if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { |
6553 |
2 |
m_sortedFunctions = sortTests( config, m_functions ); |
|
6554 |
1 |
m_currentSortOrder = config.runOrder(); |
|
6555 |
} |
||
6556 |
1 |
return m_sortedFunctions; |
|
6557 |
} |
||
6558 |
|||
6559 |
private: |
||
6560 |
std::vector<TestCase> m_functions; |
||
6561 |
mutable RunTests::InWhatOrder m_currentSortOrder; |
||
6562 |
mutable std::vector<TestCase> m_sortedFunctions; |
||
6563 |
size_t m_unnamedCount; |
||
6564 |
std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised |
||
6565 |
}; |
||
6566 |
|||
6567 |
/////////////////////////////////////////////////////////////////////////// |
||
6568 |
|||
6569 |
class FreeFunctionTestCase : public SharedImpl<ITestCase> { |
||
6570 |
public: |
||
6571 |
|||
6572 |
788 |
FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} |
|
6573 |
|||
6574 |
745 |
virtual void invoke() const { |
|
6575 |
745 |
m_fun(); |
|
6576 |
745 |
} |
|
6577 |
|||
6578 |
private: |
||
6579 |
virtual ~FreeFunctionTestCase(); |
||
6580 |
|||
6581 |
TestFunction m_fun; |
||
6582 |
}; |
||
6583 |
|||
6584 |
394 |
inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { |
|
6585 |
394 |
std::string className = classOrQualifiedMethodName; |
|
6586 |
✓✗✓✗ ✗✓ |
1576 |
if( startsWith( className, "&" ) ) |
6587 |
{ |
||
6588 |
std::size_t lastColons = className.rfind( "::" ); |
||
6589 |
std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); |
||
6590 |
if( penultimateColons == std::string::npos ) |
||
6591 |
penultimateColons = 1; |
||
6592 |
className = className.substr( penultimateColons, lastColons-penultimateColons ); |
||
6593 |
} |
||
6594 |
394 |
return className; |
|
6595 |
} |
||
6596 |
|||
6597 |
394 |
void registerTestCase |
|
6598 |
( ITestCase* testCase, |
||
6599 |
char const* classOrQualifiedMethodName, |
||
6600 |
NameAndDesc const& nameAndDesc, |
||
6601 |
SourceLineInfo const& lineInfo ) { |
||
6602 |
|||
6603 |
getMutableRegistryHub().registerTest |
||
6604 |
( makeTestCase |
||
6605 |
✓✗✓✗ |
3546 |
( testCase, |
6606 |
✓✗✓✗ |
1970 |
extractClassName( classOrQualifiedMethodName ), |
6607 |
394 |
nameAndDesc.name, |
|
6608 |
394 |
nameAndDesc.description, |
|
6609 |
✓✗ | 788 |
lineInfo ) ); |
6610 |
394 |
} |
|
6611 |
394 |
void registerTestCaseFunction |
|
6612 |
( TestFunction function, |
||
6613 |
SourceLineInfo const& lineInfo, |
||
6614 |
NameAndDesc const& nameAndDesc ) { |
||
6615 |
788 |
registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); |
|
6616 |
394 |
} |
|
6617 |
|||
6618 |
/////////////////////////////////////////////////////////////////////////// |
||
6619 |
|||
6620 |
394 |
AutoReg::AutoReg |
|
6621 |
( TestFunction function, |
||
6622 |
SourceLineInfo const& lineInfo, |
||
6623 |
NameAndDesc const& nameAndDesc ) { |
||
6624 |
394 |
registerTestCaseFunction( function, lineInfo, nameAndDesc ); |
|
6625 |
394 |
} |
|
6626 |
|||
6627 |
394 |
AutoReg::~AutoReg() {} |
|
6628 |
|||
6629 |
} // end namespace Catch |
||
6630 |
|||
6631 |
// #included from: catch_reporter_registry.hpp |
||
6632 |
#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED |
||
6633 |
|||
6634 |
#include <map> |
||
6635 |
|||
6636 |
namespace Catch { |
||
6637 |
|||
6638 |
3 |
class ReporterRegistry : public IReporterRegistry { |
|
6639 |
|||
6640 |
public: |
||
6641 |
|||
6642 |
2 |
virtual ~ReporterRegistry() CATCH_OVERRIDE {} |
|
6643 |
|||
6644 |
1 |
virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE { |
|
6645 |
2 |
FactoryMap::const_iterator it = m_factories.find( name ); |
|
6646 |
✓✗ | 2 |
if( it == m_factories.end() ) |
6647 |
return CATCH_NULL; |
||
6648 |
✓✗ | 4 |
return it->second->create( ReporterConfig( config ) ); |
6649 |
} |
||
6650 |
|||
6651 |
4 |
void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) { |
|
6652 |
8 |
m_factories.insert( std::make_pair( name, factory ) ); |
|
6653 |
4 |
} |
|
6654 |
void registerListener( Ptr<IReporterFactory> const& factory ) { |
||
6655 |
m_listeners.push_back( factory ); |
||
6656 |
} |
||
6657 |
|||
6658 |
virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { |
||
6659 |
return m_factories; |
||
6660 |
} |
||
6661 |
1 |
virtual Listeners const& getListeners() const CATCH_OVERRIDE { |
|
6662 |
1 |
return m_listeners; |
|
6663 |
} |
||
6664 |
|||
6665 |
private: |
||
6666 |
FactoryMap m_factories; |
||
6667 |
Listeners m_listeners; |
||
6668 |
}; |
||
6669 |
} |
||
6670 |
|||
6671 |
// #included from: catch_exception_translator_registry.hpp |
||
6672 |
#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED |
||
6673 |
|||
6674 |
#ifdef __OBJC__ |
||
6675 |
#import "Foundation/Foundation.h" |
||
6676 |
#endif |
||
6677 |
|||
6678 |
namespace Catch { |
||
6679 |
|||
6680 |
2 |
class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { |
|
6681 |
public: |
||
6682 |
3 |
~ExceptionTranslatorRegistry() { |
|
6683 |
2 |
deleteAll( m_translators ); |
|
6684 |
1 |
} |
|
6685 |
|||
6686 |
virtual void registerTranslator( const IExceptionTranslator* translator ) { |
||
6687 |
m_translators.push_back( translator ); |
||
6688 |
} |
||
6689 |
|||
6690 |
31 |
virtual std::string translateActiveException() const { |
|
6691 |
try { |
||
6692 |
#ifdef __OBJC__ |
||
6693 |
// In Objective-C try objective-c exceptions first |
||
6694 |
@try { |
||
6695 |
return tryTranslators(); |
||
6696 |
} |
||
6697 |
@catch (NSException *exception) { |
||
6698 |
return Catch::toString( [exception description] ); |
||
6699 |
} |
||
6700 |
#else |
||
6701 |
✗✓✗✗ ✗✗✓ |
31 |
return tryTranslators(); |
6702 |
#endif |
||
6703 |
} |
||
6704 |
catch( TestFailureException& ) { |
||
6705 |
throw; |
||
6706 |
} |
||
6707 |
catch( std::exception& ex ) { |
||
6708 |
return ex.what(); |
||
6709 |
} |
||
6710 |
catch( std::string& msg ) { |
||
6711 |
return msg; |
||
6712 |
} |
||
6713 |
catch( const char* msg ) { |
||
6714 |
return msg; |
||
6715 |
} |
||
6716 |
62 |
catch(...) { |
|
6717 |
✓✗ | 93 |
return "Unknown exception"; |
6718 |
} |
||
6719 |
} |
||
6720 |
|||
6721 |
31 |
std::string tryTranslators() const { |
|
6722 |
✓✗ | 62 |
if( m_translators.empty() ) |
6723 |
31 |
throw; |
|
6724 |
else |
||
6725 |
return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); |
||
6726 |
} |
||
6727 |
|||
6728 |
private: |
||
6729 |
std::vector<const IExceptionTranslator*> m_translators; |
||
6730 |
}; |
||
6731 |
} |
||
6732 |
|||
6733 |
namespace Catch { |
||
6734 |
|||
6735 |
namespace { |
||
6736 |
|||
6737 |
3 |
class RegistryHub : public IRegistryHub, public IMutableRegistryHub { |
|
6738 |
|||
6739 |
RegistryHub( RegistryHub const& ); |
||
6740 |
void operator=( RegistryHub const& ); |
||
6741 |
|||
6742 |
public: // IRegistryHub |
||
6743 |
3 |
RegistryHub() { |
|
6744 |
1 |
} |
|
6745 |
2 |
virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { |
|
6746 |
2 |
return m_reporterRegistry; |
|
6747 |
} |
||
6748 |
1 |
virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { |
|
6749 |
1 |
return m_testCaseRegistry; |
|
6750 |
} |
||
6751 |
31 |
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { |
|
6752 |
31 |
return m_exceptionTranslatorRegistry; |
|
6753 |
} |
||
6754 |
|||
6755 |
public: // IMutableRegistryHub |
||
6756 |
4 |
virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE { |
|
6757 |
4 |
m_reporterRegistry.registerReporter( name, factory ); |
|
6758 |
4 |
} |
|
6759 |
virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE { |
||
6760 |
m_reporterRegistry.registerListener( factory ); |
||
6761 |
} |
||
6762 |
394 |
virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { |
|
6763 |
394 |
m_testCaseRegistry.registerTest( testInfo ); |
|
6764 |
394 |
} |
|
6765 |
virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { |
||
6766 |
m_exceptionTranslatorRegistry.registerTranslator( translator ); |
||
6767 |
} |
||
6768 |
|||
6769 |
private: |
||
6770 |
TestRegistry m_testCaseRegistry; |
||
6771 |
ReporterRegistry m_reporterRegistry; |
||
6772 |
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; |
||
6773 |
}; |
||
6774 |
|||
6775 |
// Single, global, instance |
||
6776 |
434 |
inline RegistryHub*& getTheRegistryHub() { |
|
6777 |
static RegistryHub* theRegistryHub = CATCH_NULL; |
||
6778 |
✓✓ | 434 |
if( !theRegistryHub ) |
6779 |
✓✗ | 1 |
theRegistryHub = new RegistryHub(); |
6780 |
434 |
return theRegistryHub; |
|
6781 |
} |
||
6782 |
} |
||
6783 |
|||
6784 |
IRegistryHub& getRegistryHub() { |
||
6785 |
34 |
return *getTheRegistryHub(); |
|
6786 |
} |
||
6787 |
IMutableRegistryHub& getMutableRegistryHub() { |
||
6788 |
398 |
return *getTheRegistryHub(); |
|
6789 |
} |
||
6790 |
1 |
void cleanUp() { |
|
6791 |
✓✗ | 1 |
delete getTheRegistryHub(); |
6792 |
1 |
getTheRegistryHub() = CATCH_NULL; |
|
6793 |
cleanUpContext(); |
||
6794 |
1 |
} |
|
6795 |
31 |
std::string translateActiveException() { |
|
6796 |
31 |
return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); |
|
6797 |
} |
||
6798 |
|||
6799 |
} // end namespace Catch |
||
6800 |
|||
6801 |
// #included from: catch_notimplemented_exception.hpp |
||
6802 |
#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED |
||
6803 |
|||
6804 |
#include <ostream> |
||
6805 |
|||
6806 |
namespace Catch { |
||
6807 |
|||
6808 |
NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) |
||
6809 |
: m_lineInfo( lineInfo ) { |
||
6810 |
std::ostringstream oss; |
||
6811 |
oss << lineInfo << ": function "; |
||
6812 |
oss << "not implemented"; |
||
6813 |
m_what = oss.str(); |
||
6814 |
} |
||
6815 |
|||
6816 |
const char* NotImplementedException::what() const CATCH_NOEXCEPT { |
||
6817 |
return m_what.c_str(); |
||
6818 |
} |
||
6819 |
|||
6820 |
} // end namespace Catch |
||
6821 |
|||
6822 |
// #included from: catch_context_impl.hpp |
||
6823 |
#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED |
||
6824 |
|||
6825 |
// #included from: catch_stream.hpp |
||
6826 |
#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED |
||
6827 |
|||
6828 |
#include <stdexcept> |
||
6829 |
#include <cstdio> |
||
6830 |
#include <iostream> |
||
6831 |
|||
6832 |
namespace Catch { |
||
6833 |
|||
6834 |
template<typename WriterF, size_t bufferSize=256> |
||
6835 |
class StreamBufImpl : public StreamBufBase { |
||
6836 |
char data[bufferSize]; |
||
6837 |
WriterF m_writer; |
||
6838 |
|||
6839 |
public: |
||
6840 |
StreamBufImpl() { |
||
6841 |
setp( data, data + sizeof(data) ); |
||
6842 |
} |
||
6843 |
|||
6844 |
~StreamBufImpl() CATCH_NOEXCEPT { |
||
6845 |
sync(); |
||
6846 |
} |
||
6847 |
|||
6848 |
private: |
||
6849 |
int overflow( int c ) { |
||
6850 |
sync(); |
||
6851 |
|||
6852 |
if( c != EOF ) { |
||
6853 |
if( pbase() == epptr() ) |
||
6854 |
m_writer( std::string( 1, static_cast<char>( c ) ) ); |
||
6855 |
else |
||
6856 |
sputc( static_cast<char>( c ) ); |
||
6857 |
} |
||
6858 |
return 0; |
||
6859 |
} |
||
6860 |
|||
6861 |
int sync() { |
||
6862 |
if( pbase() != pptr() ) { |
||
6863 |
m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); |
||
6864 |
setp( pbase(), epptr() ); |
||
6865 |
} |
||
6866 |
return 0; |
||
6867 |
} |
||
6868 |
}; |
||
6869 |
|||
6870 |
/////////////////////////////////////////////////////////////////////////// |
||
6871 |
|||
6872 |
FileStream::FileStream( std::string const& filename ) { |
||
6873 |
m_ofs.open( filename.c_str() ); |
||
6874 |
if( m_ofs.fail() ) { |
||
6875 |
std::ostringstream oss; |
||
6876 |
oss << "Unable to open file: '" << filename << "'"; |
||
6877 |
throw std::domain_error( oss.str() ); |
||
6878 |
} |
||
6879 |
} |
||
6880 |
|||
6881 |
std::ostream& FileStream::stream() const { |
||
6882 |
return m_ofs; |
||
6883 |
} |
||
6884 |
|||
6885 |
struct OutputDebugWriter { |
||
6886 |
|||
6887 |
void operator()( std::string const&str ) { |
||
6888 |
writeToDebugConsole( str ); |
||
6889 |
} |
||
6890 |
}; |
||
6891 |
|||
6892 |
DebugOutStream::DebugOutStream() |
||
6893 |
: m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ), |
||
6894 |
m_os( m_streamBuf.get() ) |
||
6895 |
{} |
||
6896 |
|||
6897 |
std::ostream& DebugOutStream::stream() const { |
||
6898 |
return m_os; |
||
6899 |
} |
||
6900 |
|||
6901 |
// Store the streambuf from cout up-front because |
||
6902 |
// cout may get redirected when running tests |
||
6903 |
1 |
CoutStream::CoutStream() |
|
6904 |
✓✗ | 1 |
: m_os( Catch::cout().rdbuf() ) |
6905 |
{} |
||
6906 |
|||
6907 |
1 |
std::ostream& CoutStream::stream() const { |
|
6908 |
1 |
return m_os; |
|
6909 |
} |
||
6910 |
|||
6911 |
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions |
||
6912 |
std::ostream& cout() { |
||
6913 |
return std::cout; |
||
6914 |
} |
||
6915 |
std::ostream& cerr() { |
||
6916 |
return std::cerr; |
||
6917 |
} |
||
6918 |
#endif |
||
6919 |
} |
||
6920 |
|||
6921 |
namespace Catch { |
||
6922 |
|||
6923 |
5 |
class Context : public IMutableContext { |
|
6924 |
|||
6925 |
4 |
Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} |
|
6926 |
Context( Context const& ); |
||
6927 |
void operator=( Context const& ); |
||
6928 |
|||
6929 |
public: // IContext |
||
6930 |
1441987 |
virtual IResultCapture* getResultCapture() { |
|
6931 |
1441987 |
return m_resultCapture; |
|
6932 |
} |
||
6933 |
virtual IRunner* getRunner() { |
||
6934 |
return m_runner; |
||
6935 |
} |
||
6936 |
virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { |
||
6937 |
return getGeneratorsForCurrentTest() |
||
6938 |
.getGeneratorInfo( fileInfo, totalSize ) |
||
6939 |
.getCurrentIndex(); |
||
6940 |
} |
||
6941 |
394 |
virtual bool advanceGeneratorsForCurrentTest() { |
|
6942 |
394 |
IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); |
|
6943 |
✗✓✗✗ |
394 |
return generators && generators->moveNext(); |
6944 |
} |
||
6945 |
|||
6946 |
164079 |
virtual Ptr<IConfig const> getConfig() const { |
|
6947 |
328158 |
return m_config; |
|
6948 |
} |
||
6949 |
|||
6950 |
public: // IMutableContext |
||
6951 |
1 |
virtual void setResultCapture( IResultCapture* resultCapture ) { |
|
6952 |
1 |
m_resultCapture = resultCapture; |
|
6953 |
1 |
} |
|
6954 |
1 |
virtual void setRunner( IRunner* runner ) { |
|
6955 |
1 |
m_runner = runner; |
|
6956 |
1 |
} |
|
6957 |
1 |
virtual void setConfig( Ptr<IConfig const> const& config ) { |
|
6958 |
1 |
m_config = config; |
|
6959 |
1 |
} |
|
6960 |
|||
6961 |
friend IMutableContext& getCurrentMutableContext(); |
||
6962 |
|||
6963 |
private: |
||
6964 |
394 |
IGeneratorsForTest* findGeneratorsForCurrentTest() { |
|
6965 |
788 |
std::string testName = getResultCapture()->getCurrentTestName(); |
|
6966 |
|||
6967 |
std::map<std::string, IGeneratorsForTest*>::const_iterator it = |
||
6968 |
1182 |
m_generatorsByTestName.find( testName ); |
|
6969 |
1182 |
return it != m_generatorsByTestName.end() |
|
6970 |
✗✓ | 394 |
? it->second |
6971 |
394 |
: CATCH_NULL; |
|
6972 |
} |
||
6973 |
|||
6974 |
IGeneratorsForTest& getGeneratorsForCurrentTest() { |
||
6975 |
IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); |
||
6976 |
if( !generators ) { |
||
6977 |
std::string testName = getResultCapture()->getCurrentTestName(); |
||
6978 |
generators = createGeneratorsForTest(); |
||
6979 |
m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); |
||
6980 |
} |
||
6981 |
return *generators; |
||
6982 |
} |
||
6983 |
|||
6984 |
private: |
||
6985 |
Ptr<IConfig const> m_config; |
||
6986 |
IRunner* m_runner; |
||
6987 |
IResultCapture* m_resultCapture; |
||
6988 |
std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName; |
||
6989 |
}; |
||
6990 |
|||
6991 |
namespace { |
||
6992 |
Context* currentContext = CATCH_NULL; |
||
6993 |
} |
||
6994 |
1606067 |
IMutableContext& getCurrentMutableContext() { |
|
6995 |
✓✓ | 1606067 |
if( !currentContext ) |
6996 |
2 |
currentContext = new Context(); |
|
6997 |
1606067 |
return *currentContext; |
|
6998 |
} |
||
6999 |
IContext& getCurrentContext() { |
||
7000 |
✓✓✗✗ |
1606066 |
return getCurrentMutableContext(); |
7001 |
} |
||
7002 |
|||
7003 |
void cleanUpContext() { |
||
7004 |
✗✗✓✗ |
1 |
delete currentContext; |
7005 |
1 |
currentContext = CATCH_NULL; |
|
7006 |
} |
||
7007 |
} |
||
7008 |
|||
7009 |
// #included from: catch_console_colour_impl.hpp |
||
7010 |
#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED |
||
7011 |
|||
7012 |
namespace Catch { |
||
7013 |
namespace { |
||
7014 |
|||
7015 |
struct IColourImpl { |
||
7016 |
virtual ~IColourImpl() {} |
||
7017 |
virtual void use( Colour::Code _colourCode ) = 0; |
||
7018 |
}; |
||
7019 |
|||
7020 |
1 |
struct NoColourImpl : IColourImpl { |
|
7021 |
8 |
void use( Colour::Code ) {} |
|
7022 |
|||
7023 |
1 |
static IColourImpl* instance() { |
|
7024 |
✓✗✓✗ |
1 |
static NoColourImpl s_instance; |
7025 |
1 |
return &s_instance; |
|
7026 |
} |
||
7027 |
}; |
||
7028 |
|||
7029 |
} // anon namespace |
||
7030 |
} // namespace Catch |
||
7031 |
|||
7032 |
#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) |
||
7033 |
# ifdef CATCH_PLATFORM_WINDOWS |
||
7034 |
# define CATCH_CONFIG_COLOUR_WINDOWS |
||
7035 |
# else |
||
7036 |
# define CATCH_CONFIG_COLOUR_ANSI |
||
7037 |
# endif |
||
7038 |
#endif |
||
7039 |
|||
7040 |
#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// |
||
7041 |
|||
7042 |
#ifndef NOMINMAX |
||
7043 |
#define NOMINMAX |
||
7044 |
#endif |
||
7045 |
|||
7046 |
#ifdef __AFXDLL |
||
7047 |
#include <AfxWin.h> |
||
7048 |
#else |
||
7049 |
#include <windows.h> |
||
7050 |
#endif |
||
7051 |
|||
7052 |
namespace Catch { |
||
7053 |
namespace { |
||
7054 |
|||
7055 |
class Win32ColourImpl : public IColourImpl { |
||
7056 |
public: |
||
7057 |
Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) |
||
7058 |
{ |
||
7059 |
CONSOLE_SCREEN_BUFFER_INFO csbiInfo; |
||
7060 |
GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); |
||
7061 |
originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); |
||
7062 |
originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); |
||
7063 |
} |
||
7064 |
|||
7065 |
virtual void use( Colour::Code _colourCode ) { |
||
7066 |
switch( _colourCode ) { |
||
7067 |
case Colour::None: return setTextAttribute( originalForegroundAttributes ); |
||
7068 |
case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); |
||
7069 |
case Colour::Red: return setTextAttribute( FOREGROUND_RED ); |
||
7070 |
case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); |
||
7071 |
case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); |
||
7072 |
case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); |
||
7073 |
case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); |
||
7074 |
case Colour::Grey: return setTextAttribute( 0 ); |
||
7075 |
|||
7076 |
case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); |
||
7077 |
case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); |
||
7078 |
case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); |
||
7079 |
case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); |
||
7080 |
|||
7081 |
case Colour::Bright: throw std::logic_error( "not a colour" ); |
||
7082 |
} |
||
7083 |
} |
||
7084 |
|||
7085 |
private: |
||
7086 |
void setTextAttribute( WORD _textAttribute ) { |
||
7087 |
SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); |
||
7088 |
} |
||
7089 |
HANDLE stdoutHandle; |
||
7090 |
WORD originalForegroundAttributes; |
||
7091 |
WORD originalBackgroundAttributes; |
||
7092 |
}; |
||
7093 |
|||
7094 |
IColourImpl* platformColourInstance() { |
||
7095 |
static Win32ColourImpl s_instance; |
||
7096 |
|||
7097 |
Ptr<IConfig const> config = getCurrentContext().getConfig(); |
||
7098 |
UseColour::YesOrNo colourMode = config |
||
7099 |
? config->useColour() |
||
7100 |
: UseColour::Auto; |
||
7101 |
if( colourMode == UseColour::Auto ) |
||
7102 |
colourMode = !isDebuggerActive() |
||
7103 |
? UseColour::Yes |
||
7104 |
: UseColour::No; |
||
7105 |
return colourMode == UseColour::Yes |
||
7106 |
? &s_instance |
||
7107 |
: NoColourImpl::instance(); |
||
7108 |
} |
||
7109 |
|||
7110 |
} // end anon namespace |
||
7111 |
} // end namespace Catch |
||
7112 |
|||
7113 |
#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// |
||
7114 |
|||
7115 |
#include <unistd.h> |
||
7116 |
|||
7117 |
namespace Catch { |
||
7118 |
namespace { |
||
7119 |
|||
7120 |
// use POSIX/ ANSI console terminal codes |
||
7121 |
// Thanks to Adam Strzelecki for original contribution |
||
7122 |
// (http://github.com/nanoant) |
||
7123 |
// https://github.com/philsquared/Catch/pull/131 |
||
7124 |
class PosixColourImpl : public IColourImpl { |
||
7125 |
public: |
||
7126 |
virtual void use( Colour::Code _colourCode ) { |
||
7127 |
switch( _colourCode ) { |
||
7128 |
case Colour::None: |
||
7129 |
case Colour::White: return setColour( "[0m" ); |
||
7130 |
case Colour::Red: return setColour( "[0;31m" ); |
||
7131 |
case Colour::Green: return setColour( "[0;32m" ); |
||
7132 |
case Colour::Blue: return setColour( "[0:34m" ); |
||
7133 |
case Colour::Cyan: return setColour( "[0;36m" ); |
||
7134 |
case Colour::Yellow: return setColour( "[0;33m" ); |
||
7135 |
case Colour::Grey: return setColour( "[1;30m" ); |
||
7136 |
|||
7137 |
case Colour::LightGrey: return setColour( "[0;37m" ); |
||
7138 |
case Colour::BrightRed: return setColour( "[1;31m" ); |
||
7139 |
case Colour::BrightGreen: return setColour( "[1;32m" ); |
||
7140 |
case Colour::BrightWhite: return setColour( "[1;37m" ); |
||
7141 |
|||
7142 |
case Colour::Bright: throw std::logic_error( "not a colour" ); |
||
7143 |
} |
||
7144 |
} |
||
7145 |
static IColourImpl* instance() { |
||
7146 |
static PosixColourImpl s_instance; |
||
7147 |
return &s_instance; |
||
7148 |
} |
||
7149 |
|||
7150 |
private: |
||
7151 |
void setColour( const char* _escapeCode ) { |
||
7152 |
Catch::cout() << '\033' << _escapeCode; |
||
7153 |
} |
||
7154 |
}; |
||
7155 |
|||
7156 |
1 |
IColourImpl* platformColourInstance() { |
|
7157 |
2 |
Ptr<IConfig const> config = getCurrentContext().getConfig(); |
|
7158 |
UseColour::YesOrNo colourMode = config |
||
7159 |
✓✗✓✗ |
1 |
? config->useColour() |
7160 |
2 |
: UseColour::Auto; |
|
7161 |
✓✗ | 1 |
if( colourMode == UseColour::Auto ) |
7162 |
✓✗ | 1 |
colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) |
7163 |
? UseColour::Yes |
||
7164 |
: UseColour::No; |
||
7165 |
return colourMode == UseColour::Yes |
||
7166 |
✗✓ | 1 |
? PosixColourImpl::instance() |
7167 |
2 |
: NoColourImpl::instance(); |
|
7168 |
} |
||
7169 |
|||
7170 |
} // end anon namespace |
||
7171 |
} // end namespace Catch |
||
7172 |
|||
7173 |
#else // not Windows or ANSI /////////////////////////////////////////////// |
||
7174 |
|||
7175 |
namespace Catch { |
||
7176 |
|||
7177 |
static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } |
||
7178 |
|||
7179 |
} // end namespace Catch |
||
7180 |
|||
7181 |
#endif // Windows/ ANSI/ None |
||
7182 |
|||
7183 |
namespace Catch { |
||
7184 |
|||
7185 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗ |
4 |
Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } |
7186 |
Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; } |
||
7187 |
✗✗ | 4 |
Colour::~Colour(){ if( !m_moved ) use( None ); } |
7188 |
|||
7189 |
8 |
void Colour::use( Code _colourCode ) { |
|
7190 |
✓✓✓✗ ✓✗ |
8 |
static IColourImpl* impl = platformColourInstance(); |
7191 |
8 |
impl->use( _colourCode ); |
|
7192 |
8 |
} |
|
7193 |
|||
7194 |
} // end namespace Catch |
||
7195 |
|||
7196 |
// #included from: catch_generators_impl.hpp |
||
7197 |
#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED |
||
7198 |
|||
7199 |
#include <vector> |
||
7200 |
#include <string> |
||
7201 |
#include <map> |
||
7202 |
|||
7203 |
namespace Catch { |
||
7204 |
|||
7205 |
struct GeneratorInfo : IGeneratorInfo { |
||
7206 |
|||
7207 |
GeneratorInfo( std::size_t size ) |
||
7208 |
: m_size( size ), |
||
7209 |
m_currentIndex( 0 ) |
||
7210 |
{} |
||
7211 |
|||
7212 |
bool moveNext() { |
||
7213 |
if( ++m_currentIndex == m_size ) { |
||
7214 |
m_currentIndex = 0; |
||
7215 |
return false; |
||
7216 |
} |
||
7217 |
return true; |
||
7218 |
} |
||
7219 |
|||
7220 |
std::size_t getCurrentIndex() const { |
||
7221 |
return m_currentIndex; |
||
7222 |
} |
||
7223 |
|||
7224 |
std::size_t m_size; |
||
7225 |
std::size_t m_currentIndex; |
||
7226 |
}; |
||
7227 |
|||
7228 |
/////////////////////////////////////////////////////////////////////////// |
||
7229 |
|||
7230 |
class GeneratorsForTest : public IGeneratorsForTest { |
||
7231 |
|||
7232 |
public: |
||
7233 |
~GeneratorsForTest() { |
||
7234 |
deleteAll( m_generatorsInOrder ); |
||
7235 |
} |
||
7236 |
|||
7237 |
IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { |
||
7238 |
std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo ); |
||
7239 |
if( it == m_generatorsByName.end() ) { |
||
7240 |
IGeneratorInfo* info = new GeneratorInfo( size ); |
||
7241 |
m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); |
||
7242 |
m_generatorsInOrder.push_back( info ); |
||
7243 |
return *info; |
||
7244 |
} |
||
7245 |
return *it->second; |
||
7246 |
} |
||
7247 |
|||
7248 |
bool moveNext() { |
||
7249 |
std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin(); |
||
7250 |
std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end(); |
||
7251 |
for(; it != itEnd; ++it ) { |
||
7252 |
if( (*it)->moveNext() ) |
||
7253 |
return true; |
||
7254 |
} |
||
7255 |
return false; |
||
7256 |
} |
||
7257 |
|||
7258 |
private: |
||
7259 |
std::map<std::string, IGeneratorInfo*> m_generatorsByName; |
||
7260 |
std::vector<IGeneratorInfo*> m_generatorsInOrder; |
||
7261 |
}; |
||
7262 |
|||
7263 |
IGeneratorsForTest* createGeneratorsForTest() |
||
7264 |
{ |
||
7265 |
return new GeneratorsForTest(); |
||
7266 |
} |
||
7267 |
|||
7268 |
} // end namespace Catch |
||
7269 |
|||
7270 |
// #included from: catch_assertionresult.hpp |
||
7271 |
#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED |
||
7272 |
|||
7273 |
namespace Catch { |
||
7274 |
|||
7275 |
2866591 |
AssertionInfo::AssertionInfo( std::string const& _macroName, |
|
7276 |
SourceLineInfo const& _lineInfo, |
||
7277 |
std::string const& _capturedExpression, |
||
7278 |
2866591 |
ResultDisposition::Flags _resultDisposition ) |
|
7279 |
: macroName( _macroName ), |
||
7280 |
lineInfo( _lineInfo ), |
||
7281 |
capturedExpression( _capturedExpression ), |
||
7282 |
11466364 |
resultDisposition( _resultDisposition ) |
|
7283 |
2866591 |
{} |
|
7284 |
|||
7285 |
3 |
AssertionResult::AssertionResult() {} |
|
7286 |
|||
7287 |
1432923 |
AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) |
|
7288 |
: m_info( info ), |
||
7289 |
✓✗ | 1432923 |
m_resultData( data ) |
7290 |
1432923 |
{} |
|
7291 |
|||
7292 |
2865847 |
AssertionResult::~AssertionResult() {} |
|
7293 |
|||
7294 |
// Result was a success |
||
7295 |
bool AssertionResult::succeeded() const { |
||
7296 |
return Catch::isOk( m_resultData.resultType ); |
||
7297 |
} |
||
7298 |
|||
7299 |
// Result was a success, or failure is suppressed |
||
7300 |
bool AssertionResult::isOk() const { |
||
7301 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✗✗✗ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ |
5731692 |
return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); |
7302 |
} |
||
7303 |
|||
7304 |
ResultWas::OfType AssertionResult::getResultType() const { |
||
7305 |
2865846 |
return m_resultData.resultType; |
|
7306 |
} |
||
7307 |
|||
7308 |
bool AssertionResult::hasExpression() const { |
||
7309 |
return !m_info.capturedExpression.empty(); |
||
7310 |
} |
||
7311 |
|||
7312 |
bool AssertionResult::hasMessage() const { |
||
7313 |
2865846 |
return !m_resultData.message.empty(); |
|
7314 |
} |
||
7315 |
|||
7316 |
std::string AssertionResult::getExpression() const { |
||
7317 |
if( isFalseTest( m_info.resultDisposition ) ) |
||
7318 |
return "!" + m_info.capturedExpression; |
||
7319 |
else |
||
7320 |
return m_info.capturedExpression; |
||
7321 |
} |
||
7322 |
std::string AssertionResult::getExpressionInMacro() const { |
||
7323 |
if( m_info.macroName.empty() ) |
||
7324 |
return m_info.capturedExpression; |
||
7325 |
else |
||
7326 |
return m_info.macroName + "( " + m_info.capturedExpression + " )"; |
||
7327 |
} |
||
7328 |
|||
7329 |
bool AssertionResult::hasExpandedExpression() const { |
||
7330 |
return hasExpression() && getExpandedExpression() != getExpression(); |
||
7331 |
} |
||
7332 |
|||
7333 |
std::string AssertionResult::getExpandedExpression() const { |
||
7334 |
return m_resultData.reconstructedExpression; |
||
7335 |
} |
||
7336 |
|||
7337 |
std::string AssertionResult::getMessage() const { |
||
7338 |
return m_resultData.message; |
||
7339 |
} |
||
7340 |
SourceLineInfo AssertionResult::getSourceInfo() const { |
||
7341 |
return m_info.lineInfo; |
||
7342 |
} |
||
7343 |
|||
7344 |
std::string AssertionResult::getTestMacroName() const { |
||
7345 |
return m_info.macroName; |
||
7346 |
} |
||
7347 |
|||
7348 |
} // end namespace Catch |
||
7349 |
|||
7350 |
// #included from: catch_test_case_info.hpp |
||
7351 |
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED |
||
7352 |
|||
7353 |
namespace Catch { |
||
7354 |
|||
7355 |
inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { |
||
7356 |
if( startsWith( tag, "." ) || |
||
7357 |
tag == "hide" || |
||
7358 |
tag == "!hide" ) |
||
7359 |
return TestCaseInfo::IsHidden; |
||
7360 |
else if( tag == "!throws" ) |
||
7361 |
return TestCaseInfo::Throws; |
||
7362 |
else if( tag == "!shouldfail" ) |
||
7363 |
return TestCaseInfo::ShouldFail; |
||
7364 |
else if( tag == "!mayfail" ) |
||
7365 |
return TestCaseInfo::MayFail; |
||
7366 |
else |
||
7367 |
return TestCaseInfo::None; |
||
7368 |
} |
||
7369 |
inline bool isReservedTag( std::string const& tag ) { |
||
7370 |
return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); |
||
7371 |
} |
||
7372 |
inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { |
||
7373 |
if( isReservedTag( tag ) ) { |
||
7374 |
{ |
||
7375 |
Colour colourGuard( Colour::Red ); |
||
7376 |
Catch::cerr() |
||
7377 |
<< "Tag name [" << tag << "] not allowed.\n" |
||
7378 |
<< "Tag names starting with non alpha-numeric characters are reserved\n"; |
||
7379 |
} |
||
7380 |
{ |
||
7381 |
Colour colourGuard( Colour::FileName ); |
||
7382 |
Catch::cerr() << _lineInfo << std::endl; |
||
7383 |
} |
||
7384 |
exit(1); |
||
7385 |
} |
||
7386 |
} |
||
7387 |
|||
7388 |
394 |
TestCase makeTestCase( ITestCase* _testCase, |
|
7389 |
std::string const& _className, |
||
7390 |
std::string const& _name, |
||
7391 |
std::string const& _descOrTags, |
||
7392 |
SourceLineInfo const& _lineInfo ) |
||
7393 |
{ |
||
7394 |
✓✗ | 1576 |
bool isHidden( startsWith( _name, "./" ) ); // Legacy support |
7395 |
|||
7396 |
// Parse out tags |
||
7397 |
788 |
std::set<std::string> tags; |
|
7398 |
1576 |
std::string desc, tag; |
|
7399 |
394 |
bool inTag = false; |
|
7400 |
✓✓ | 846 |
for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { |
7401 |
452 |
char c = _descOrTags[i]; |
|
7402 |
✓✗ | 452 |
if( !inTag ) { |
7403 |
✓✗ | 452 |
if( c == '[' ) |
7404 |
inTag = true; |
||
7405 |
else |
||
7406 |
452 |
desc += c; |
|
7407 |
} |
||
7408 |
else { |
||
7409 |
if( c == ']' ) { |
||
7410 |
TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); |
||
7411 |
if( prop == TestCaseInfo::IsHidden ) |
||
7412 |
isHidden = true; |
||
7413 |
else if( prop == TestCaseInfo::None ) |
||
7414 |
enforceNotReservedTag( tag, _lineInfo ); |
||
7415 |
|||
7416 |
tags.insert( tag ); |
||
7417 |
tag.clear(); |
||
7418 |
inTag = false; |
||
7419 |
} |
||
7420 |
else |
||
7421 |
tag += c; |
||
7422 |
} |
||
7423 |
} |
||
7424 |
✗✓ | 394 |
if( isHidden ) { |
7425 |
tags.insert( "hide" ); |
||
7426 |
tags.insert( "." ); |
||
7427 |
} |
||
7428 |
|||
7429 |
✓✗ | 788 |
TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); |
7430 |
✓✗ | 788 |
return TestCase( _testCase, info ); |
7431 |
} |
||
7432 |
|||
7433 |
394 |
void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags ) |
|
7434 |
{ |
||
7435 |
788 |
testCaseInfo.tags = tags; |
|
7436 |
788 |
testCaseInfo.lcaseTags.clear(); |
|
7437 |
|||
7438 |
788 |
std::ostringstream oss; |
|
7439 |
✗✓ | 788 |
for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { |
7440 |
oss << "[" << *it << "]"; |
||
7441 |
std::string lcaseTag = toLower( *it ); |
||
7442 |
testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); |
||
7443 |
testCaseInfo.lcaseTags.insert( lcaseTag ); |
||
7444 |
} |
||
7445 |
788 |
testCaseInfo.tagsAsString = oss.str(); |
|
7446 |
394 |
} |
|
7447 |
|||
7448 |
394 |
TestCaseInfo::TestCaseInfo( std::string const& _name, |
|
7449 |
std::string const& _className, |
||
7450 |
std::string const& _description, |
||
7451 |
std::set<std::string> const& _tags, |
||
7452 |
394 |
SourceLineInfo const& _lineInfo ) |
|
7453 |
: name( _name ), |
||
7454 |
className( _className ), |
||
7455 |
description( _description ), |
||
7456 |
lineInfo( _lineInfo ), |
||
7457 |
3152 |
properties( None ) |
|
7458 |
{ |
||
7459 |
✓✗ | 394 |
setTags( *this, _tags ); |
7460 |
394 |
} |
|
7461 |
|||
7462 |
3269 |
TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) |
|
7463 |
: name( other.name ), |
||
7464 |
className( other.className ), |
||
7465 |
description( other.description ), |
||
7466 |
tags( other.tags ), |
||
7467 |
lcaseTags( other.lcaseTags ), |
||
7468 |
tagsAsString( other.tagsAsString ), |
||
7469 |
lineInfo( other.lineInfo ), |
||
7470 |
26152 |
properties( other.properties ) |
|
7471 |
3269 |
{} |
|
7472 |
|||
7473 |
bool TestCaseInfo::isHidden() const { |
||
7474 |
return ( properties & IsHidden ) != 0; |
||
7475 |
} |
||
7476 |
bool TestCaseInfo::throws() const { |
||
7477 |
return ( properties & Throws ) != 0; |
||
7478 |
} |
||
7479 |
bool TestCaseInfo::okToFail() const { |
||
7480 |
745 |
return ( properties & (ShouldFail | MayFail ) ) != 0; |
|
7481 |
} |
||
7482 |
bool TestCaseInfo::expectedToFail() const { |
||
7483 |
394 |
return ( properties & (ShouldFail ) ) != 0; |
|
7484 |
} |
||
7485 |
|||
7486 |
788 |
TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} |
|
7487 |
|||
7488 |
1693 |
TestCase::TestCase( TestCase const& other ) |
|
7489 |
: TestCaseInfo( other ), |
||
7490 |
3386 |
test( other.test ) |
|
7491 |
1693 |
{} |
|
7492 |
|||
7493 |
TestCase TestCase::withName( std::string const& _newName ) const { |
||
7494 |
TestCase other( *this ); |
||
7495 |
other.name = _newName; |
||
7496 |
return other; |
||
7497 |
} |
||
7498 |
|||
7499 |
void TestCase::swap( TestCase& other ) { |
||
7500 |
test.swap( other.test ); |
||
7501 |
name.swap( other.name ); |
||
7502 |
className.swap( other.className ); |
||
7503 |
description.swap( other.description ); |
||
7504 |
tags.swap( other.tags ); |
||
7505 |
lcaseTags.swap( other.lcaseTags ); |
||
7506 |
tagsAsString.swap( other.tagsAsString ); |
||
7507 |
std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties ); |
||
7508 |
std::swap( lineInfo, other.lineInfo ); |
||
7509 |
} |
||
7510 |
|||
7511 |
void TestCase::invoke() const { |
||
7512 |
✓✗ | 1490 |
test->invoke(); |
7513 |
} |
||
7514 |
|||
7515 |
bool TestCase::operator == ( TestCase const& other ) const { |
||
7516 |
return test.get() == other.test.get() && |
||
7517 |
name == other.name && |
||
7518 |
className == other.className; |
||
7519 |
} |
||
7520 |
|||
7521 |
bool TestCase::operator < ( TestCase const& other ) const { |
||
7522 |
8498 |
return name < other.name; |
|
7523 |
} |
||
7524 |
TestCase& TestCase::operator = ( TestCase const& other ) { |
||
7525 |
TestCase temp( other ); |
||
7526 |
swap( temp ); |
||
7527 |
return *this; |
||
7528 |
} |
||
7529 |
|||
7530 |
TestCaseInfo const& TestCase::getTestCaseInfo() const |
||
7531 |
{ |
||
7532 |
1139 |
return *this; |
|
7533 |
} |
||
7534 |
|||
7535 |
} // end namespace Catch |
||
7536 |
|||
7537 |
// #included from: catch_version.hpp |
||
7538 |
#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED |
||
7539 |
|||
7540 |
namespace Catch { |
||
7541 |
|||
7542 |
Version::Version |
||
7543 |
( unsigned int _majorVersion, |
||
7544 |
unsigned int _minorVersion, |
||
7545 |
unsigned int _patchNumber, |
||
7546 |
std::string const& _branchName, |
||
7547 |
1 |
unsigned int _buildNumber ) |
|
7548 |
: majorVersion( _majorVersion ), |
||
7549 |
minorVersion( _minorVersion ), |
||
7550 |
patchNumber( _patchNumber ), |
||
7551 |
branchName( _branchName ), |
||
7552 |
2 |
buildNumber( _buildNumber ) |
|
7553 |
{} |
||
7554 |
|||
7555 |
std::ostream& operator << ( std::ostream& os, Version const& version ) { |
||
7556 |
os << version.majorVersion << "." |
||
7557 |
<< version.minorVersion << "." |
||
7558 |
<< version.patchNumber; |
||
7559 |
|||
7560 |
if( !version.branchName.empty() ) { |
||
7561 |
os << "-" << version.branchName |
||
7562 |
<< "." << version.buildNumber; |
||
7563 |
} |
||
7564 |
return os; |
||
7565 |
} |
||
7566 |
|||
7567 |
5 |
Version libraryVersion( 1, 5, 1, "", 0 ); |
|
7568 |
|||
7569 |
} |
||
7570 |
|||
7571 |
// #included from: catch_message.hpp |
||
7572 |
#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED |
||
7573 |
|||
7574 |
namespace Catch { |
||
7575 |
|||
7576 |
MessageInfo::MessageInfo( std::string const& _macroName, |
||
7577 |
SourceLineInfo const& _lineInfo, |
||
7578 |
ResultWas::OfType _type ) |
||
7579 |
: macroName( _macroName ), |
||
7580 |
lineInfo( _lineInfo ), |
||
7581 |
type( _type ), |
||
7582 |
sequence( ++globalCount ) |
||
7583 |
{} |
||
7584 |
|||
7585 |
// This may need protecting if threading support is added |
||
7586 |
unsigned int MessageInfo::globalCount = 0; |
||
7587 |
|||
7588 |
//////////////////////////////////////////////////////////////////////////// |
||
7589 |
|||
7590 |
ScopedMessage::ScopedMessage( MessageBuilder const& builder ) |
||
7591 |
: m_info( builder.m_info ) |
||
7592 |
{ |
||
7593 |
m_info.message = builder.m_stream.str(); |
||
7594 |
getResultCapture().pushScopedMessage( m_info ); |
||
7595 |
} |
||
7596 |
ScopedMessage::ScopedMessage( ScopedMessage const& other ) |
||
7597 |
: m_info( other.m_info ) |
||
7598 |
{} |
||
7599 |
|||
7600 |
ScopedMessage::~ScopedMessage() { |
||
7601 |
getResultCapture().popScopedMessage( m_info ); |
||
7602 |
} |
||
7603 |
|||
7604 |
} // end namespace Catch |
||
7605 |
|||
7606 |
// #included from: catch_legacy_reporter_adapter.hpp |
||
7607 |
#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED |
||
7608 |
|||
7609 |
// #included from: catch_legacy_reporter_adapter.h |
||
7610 |
#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED |
||
7611 |
|||
7612 |
namespace Catch |
||
7613 |
{ |
||
7614 |
// Deprecated |
||
7615 |
struct IReporter : IShared { |
||
7616 |
virtual ~IReporter(); |
||
7617 |
|||
7618 |
virtual bool shouldRedirectStdout() const = 0; |
||
7619 |
|||
7620 |
virtual void StartTesting() = 0; |
||
7621 |
virtual void EndTesting( Totals const& totals ) = 0; |
||
7622 |
virtual void StartGroup( std::string const& groupName ) = 0; |
||
7623 |
virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; |
||
7624 |
virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; |
||
7625 |
virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; |
||
7626 |
virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; |
||
7627 |
virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; |
||
7628 |
virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; |
||
7629 |
virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; |
||
7630 |
virtual void Aborted() = 0; |
||
7631 |
virtual void Result( AssertionResult const& result ) = 0; |
||
7632 |
}; |
||
7633 |
|||
7634 |
class LegacyReporterAdapter : public SharedImpl<IStreamingReporter> |
||
7635 |
{ |
||
7636 |
public: |
||
7637 |
LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter ); |
||
7638 |
virtual ~LegacyReporterAdapter(); |
||
7639 |
|||
7640 |
virtual ReporterPreferences getPreferences() const; |
||
7641 |
virtual void noMatchingTestCases( std::string const& ); |
||
7642 |
virtual void testRunStarting( TestRunInfo const& ); |
||
7643 |
virtual void testGroupStarting( GroupInfo const& groupInfo ); |
||
7644 |
virtual void testCaseStarting( TestCaseInfo const& testInfo ); |
||
7645 |
virtual void sectionStarting( SectionInfo const& sectionInfo ); |
||
7646 |
virtual void assertionStarting( AssertionInfo const& ); |
||
7647 |
virtual bool assertionEnded( AssertionStats const& assertionStats ); |
||
7648 |
virtual void sectionEnded( SectionStats const& sectionStats ); |
||
7649 |
virtual void testCaseEnded( TestCaseStats const& testCaseStats ); |
||
7650 |
virtual void testGroupEnded( TestGroupStats const& testGroupStats ); |
||
7651 |
virtual void testRunEnded( TestRunStats const& testRunStats ); |
||
7652 |
virtual void skipTest( TestCaseInfo const& ); |
||
7653 |
|||
7654 |
private: |
||
7655 |
Ptr<IReporter> m_legacyReporter; |
||
7656 |
}; |
||
7657 |
} |
||
7658 |
|||
7659 |
namespace Catch |
||
7660 |
{ |
||
7661 |
LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter ) |
||
7662 |
: m_legacyReporter( legacyReporter ) |
||
7663 |
{} |
||
7664 |
LegacyReporterAdapter::~LegacyReporterAdapter() {} |
||
7665 |
|||
7666 |
ReporterPreferences LegacyReporterAdapter::getPreferences() const { |
||
7667 |
ReporterPreferences prefs; |
||
7668 |
prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); |
||
7669 |
return prefs; |
||
7670 |
} |
||
7671 |
|||
7672 |
void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} |
||
7673 |
void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { |
||
7674 |
m_legacyReporter->StartTesting(); |
||
7675 |
} |
||
7676 |
void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { |
||
7677 |
m_legacyReporter->StartGroup( groupInfo.name ); |
||
7678 |
} |
||
7679 |
void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { |
||
7680 |
m_legacyReporter->StartTestCase( testInfo ); |
||
7681 |
} |
||
7682 |
void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { |
||
7683 |
m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); |
||
7684 |
} |
||
7685 |
void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { |
||
7686 |
// Not on legacy interface |
||
7687 |
} |
||
7688 |
|||
7689 |
bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { |
||
7690 |
if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { |
||
7691 |
for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); |
||
7692 |
it != itEnd; |
||
7693 |
++it ) { |
||
7694 |
if( it->type == ResultWas::Info ) { |
||
7695 |
ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); |
||
7696 |
rb << it->message; |
||
7697 |
rb.setResultType( ResultWas::Info ); |
||
7698 |
AssertionResult result = rb.build(); |
||
7699 |
m_legacyReporter->Result( result ); |
||
7700 |
} |
||
7701 |
} |
||
7702 |
} |
||
7703 |
m_legacyReporter->Result( assertionStats.assertionResult ); |
||
7704 |
return true; |
||
7705 |
} |
||
7706 |
void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { |
||
7707 |
if( sectionStats.missingAssertions ) |
||
7708 |
m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); |
||
7709 |
m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); |
||
7710 |
} |
||
7711 |
void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { |
||
7712 |
m_legacyReporter->EndTestCase |
||
7713 |
( testCaseStats.testInfo, |
||
7714 |
testCaseStats.totals, |
||
7715 |
testCaseStats.stdOut, |
||
7716 |
testCaseStats.stdErr ); |
||
7717 |
} |
||
7718 |
void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { |
||
7719 |
if( testGroupStats.aborting ) |
||
7720 |
m_legacyReporter->Aborted(); |
||
7721 |
m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); |
||
7722 |
} |
||
7723 |
void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { |
||
7724 |
m_legacyReporter->EndTesting( testRunStats.totals ); |
||
7725 |
} |
||
7726 |
void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { |
||
7727 |
} |
||
7728 |
} |
||
7729 |
|||
7730 |
// #included from: catch_timer.hpp |
||
7731 |
|||
7732 |
#ifdef __clang__ |
||
7733 |
#pragma clang diagnostic push |
||
7734 |
#pragma clang diagnostic ignored "-Wc++11-long-long" |
||
7735 |
#endif |
||
7736 |
|||
7737 |
#ifdef CATCH_PLATFORM_WINDOWS |
||
7738 |
#include <windows.h> |
||
7739 |
#else |
||
7740 |
#include <sys/time.h> |
||
7741 |
#endif |
||
7742 |
|||
7743 |
namespace Catch { |
||
7744 |
|||
7745 |
namespace { |
||
7746 |
#ifdef CATCH_PLATFORM_WINDOWS |
||
7747 |
uint64_t getCurrentTicks() { |
||
7748 |
static uint64_t hz=0, hzo=0; |
||
7749 |
if (!hz) { |
||
7750 |
QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) ); |
||
7751 |
QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) ); |
||
7752 |
} |
||
7753 |
uint64_t t; |
||
7754 |
QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) ); |
||
7755 |
return ((t-hzo)*1000000)/hz; |
||
7756 |
} |
||
7757 |
#else |
||
7758 |
uint64_t getCurrentTicks() { |
||
7759 |
timeval t; |
||
7760 |
10160 |
gettimeofday(&t,CATCH_NULL); |
|
7761 |
10160 |
return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec ); |
|
7762 |
} |
||
7763 |
#endif |
||
7764 |
} |
||
7765 |
|||
7766 |
void Timer::start() { |
||
7767 |
9015 |
m_ticks = getCurrentTicks(); |
|
7768 |
} |
||
7769 |
unsigned int Timer::getElapsedMicroseconds() const { |
||
7770 |
1145 |
return static_cast<unsigned int>(getCurrentTicks() - m_ticks); |
|
7771 |
} |
||
7772 |
unsigned int Timer::getElapsedMilliseconds() const { |
||
7773 |
return static_cast<unsigned int>(getElapsedMicroseconds()/1000); |
||
7774 |
} |
||
7775 |
1145 |
double Timer::getElapsedSeconds() const { |
|
7776 |
1145 |
return getElapsedMicroseconds()/1000000.0; |
|
7777 |
} |
||
7778 |
|||
7779 |
} // namespace Catch |
||
7780 |
|||
7781 |
#ifdef __clang__ |
||
7782 |
#pragma clang diagnostic pop |
||
7783 |
#endif |
||
7784 |
// #included from: catch_common.hpp |
||
7785 |
#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED |
||
7786 |
|||
7787 |
namespace Catch { |
||
7788 |
|||
7789 |
789 |
bool startsWith( std::string const& s, std::string const& prefix ) { |
|
7790 |
✓✓✓✗ ✓✓ |
1183 |
return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; |
7791 |
} |
||
7792 |
bool endsWith( std::string const& s, std::string const& suffix ) { |
||
7793 |
return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; |
||
7794 |
} |
||
7795 |
bool contains( std::string const& s, std::string const& infix ) { |
||
7796 |
return s.find( infix ) != std::string::npos; |
||
7797 |
} |
||
7798 |
1 |
void toLowerInPlace( std::string& s ) { |
|
7799 |
4 |
std::transform( s.begin(), s.end(), s.begin(), ::tolower ); |
|
7800 |
1 |
} |
|
7801 |
std::string toLower( std::string const& s ) { |
||
7802 |
1 |
std::string lc = s; |
|
7803 |
1 |
toLowerInPlace( lc ); |
|
7804 |
return lc; |
||
7805 |
} |
||
7806 |
std::string trim( std::string const& str ) { |
||
7807 |
static char const* whitespaceChars = "\n\r\t "; |
||
7808 |
std::string::size_type start = str.find_first_not_of( whitespaceChars ); |
||
7809 |
std::string::size_type end = str.find_last_not_of( whitespaceChars ); |
||
7810 |
|||
7811 |
return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; |
||
7812 |
} |
||
7813 |
|||
7814 |
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { |
||
7815 |
bool replaced = false; |
||
7816 |
std::size_t i = str.find( replaceThis ); |
||
7817 |
while( i != std::string::npos ) { |
||
7818 |
replaced = true; |
||
7819 |
str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); |
||
7820 |
if( i < str.size()-withThis.size() ) |
||
7821 |
i = str.find( replaceThis, i+withThis.size() ); |
||
7822 |
else |
||
7823 |
i = std::string::npos; |
||
7824 |
} |
||
7825 |
return replaced; |
||
7826 |
} |
||
7827 |
|||
7828 |
2 |
pluralise::pluralise( std::size_t count, std::string const& label ) |
|
7829 |
: m_count( count ), |
||
7830 |
4 |
m_label( label ) |
|
7831 |
{} |
||
7832 |
|||
7833 |
2 |
std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { |
|
7834 |
8 |
os << pluraliser.m_count << " " << pluraliser.m_label; |
|
7835 |
✓✗ | 2 |
if( pluraliser.m_count != 1 ) |
7836 |
2 |
os << "s"; |
|
7837 |
2 |
return os; |
|
7838 |
} |
||
7839 |
|||
7840 |
4 |
SourceLineInfo::SourceLineInfo() : line( 0 ){} |
|
7841 |
1441587 |
SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) |
|
7842 |
: file( _file ), |
||
7843 |
4324761 |
line( _line ) |
|
7844 |
1441587 |
{} |
|
7845 |
5756075 |
SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) |
|
7846 |
: file( other.file ), |
||
7847 |
11512150 |
line( other.line ) |
|
7848 |
{} |
||
7849 |
bool SourceLineInfo::empty() const { |
||
7850 |
return file.empty(); |
||
7851 |
} |
||
7852 |
bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { |
||
7853 |
return line == other.line && file == other.file; |
||
7854 |
} |
||
7855 |
bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { |
||
7856 |
return line < other.line || ( line == other.line && file < other.file ); |
||
7857 |
} |
||
7858 |
|||
7859 |
746 |
void seedRng( IConfig const& config ) { |
|
7860 |
✗✓ | 746 |
if( config.rngSeed() != 0 ) |
7861 |
std::srand( config.rngSeed() ); |
||
7862 |
746 |
} |
|
7863 |
unsigned int rngSeed() { |
||
7864 |
return getCurrentContext().getConfig()->rngSeed(); |
||
7865 |
} |
||
7866 |
|||
7867 |
8270 |
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { |
|
7868 |
#ifndef __GNUG__ |
||
7869 |
os << info.file << "(" << info.line << ")"; |
||
7870 |
#else |
||
7871 |
33080 |
os << info.file << ":" << info.line; |
|
7872 |
#endif |
||
7873 |
8270 |
return os; |
|
7874 |
} |
||
7875 |
|||
7876 |
void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { |
||
7877 |
std::ostringstream oss; |
||
7878 |
oss << locationInfo << ": Internal Catch error: '" << message << "'"; |
||
7879 |
if( alwaysTrue() ) |
||
7880 |
throw std::logic_error( oss.str() ); |
||
7881 |
} |
||
7882 |
} |
||
7883 |
|||
7884 |
// #included from: catch_section.hpp |
||
7885 |
#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED |
||
7886 |
|||
7887 |
namespace Catch { |
||
7888 |
|||
7889 |
9015 |
SectionInfo::SectionInfo |
|
7890 |
( SourceLineInfo const& _lineInfo, |
||
7891 |
std::string const& _name, |
||
7892 |
9015 |
std::string const& _description ) |
|
7893 |
: name( _name ), |
||
7894 |
description( _description ), |
||
7895 |
36060 |
lineInfo( _lineInfo ) |
|
7896 |
9015 |
{} |
|
7897 |
|||
7898 |
8270 |
Section::Section( SectionInfo const& info ) |
|
7899 |
: m_info( info ), |
||
7900 |
✓✗✓✗ |
41350 |
m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) |
7901 |
{ |
||
7902 |
16540 |
m_timer.start(); |
|
7903 |
8270 |
} |
|
7904 |
|||
7905 |
24810 |
Section::~Section() { |
|
7906 |
✓✓ | 8270 |
if( m_sectionIncluded ) { |
7907 |
1200 |
SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); |
|
7908 |
✗✓ | 400 |
if( std::uncaught_exception() ) |
7909 |
getResultCapture().sectionEndedEarly( endInfo ); |
||
7910 |
else |
||
7911 |
400 |
getResultCapture().sectionEnded( endInfo ); |
|
7912 |
} |
||
7913 |
8270 |
} |
|
7914 |
|||
7915 |
// This indicates whether the section should be executed or not |
||
7916 |
8270 |
Section::operator bool() const { |
|
7917 |
8270 |
return m_sectionIncluded; |
|
7918 |
} |
||
7919 |
|||
7920 |
} // end namespace Catch |
||
7921 |
|||
7922 |
// #included from: catch_debugger.hpp |
||
7923 |
#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED |
||
7924 |
|||
7925 |
#include <iostream> |
||
7926 |
|||
7927 |
#ifdef CATCH_PLATFORM_MAC |
||
7928 |
|||
7929 |
#include <assert.h> |
||
7930 |
#include <stdbool.h> |
||
7931 |
#include <sys/types.h> |
||
7932 |
#include <unistd.h> |
||
7933 |
#include <sys/sysctl.h> |
||
7934 |
|||
7935 |
namespace Catch{ |
||
7936 |
|||
7937 |
// The following function is taken directly from the following technical note: |
||
7938 |
// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html |
||
7939 |
|||
7940 |
// Returns true if the current process is being debugged (either |
||
7941 |
// running under the debugger or has a debugger attached post facto). |
||
7942 |
bool isDebuggerActive(){ |
||
7943 |
|||
7944 |
int mib[4]; |
||
7945 |
struct kinfo_proc info; |
||
7946 |
size_t size; |
||
7947 |
|||
7948 |
// Initialize the flags so that, if sysctl fails for some bizarre |
||
7949 |
// reason, we get a predictable result. |
||
7950 |
|||
7951 |
info.kp_proc.p_flag = 0; |
||
7952 |
|||
7953 |
// Initialize mib, which tells sysctl the info we want, in this case |
||
7954 |
// we're looking for information about a specific process ID. |
||
7955 |
|||
7956 |
mib[0] = CTL_KERN; |
||
7957 |
mib[1] = KERN_PROC; |
||
7958 |
mib[2] = KERN_PROC_PID; |
||
7959 |
mib[3] = getpid(); |
||
7960 |
|||
7961 |
// Call sysctl. |
||
7962 |
|||
7963 |
size = sizeof(info); |
||
7964 |
if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { |
||
7965 |
Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; |
||
7966 |
return false; |
||
7967 |
} |
||
7968 |
|||
7969 |
// We're being debugged if the P_TRACED flag is set. |
||
7970 |
|||
7971 |
return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); |
||
7972 |
} |
||
7973 |
} // namespace Catch |
||
7974 |
|||
7975 |
#elif defined(_MSC_VER) |
||
7976 |
extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); |
||
7977 |
namespace Catch { |
||
7978 |
bool isDebuggerActive() { |
||
7979 |
return IsDebuggerPresent() != 0; |
||
7980 |
} |
||
7981 |
} |
||
7982 |
#elif defined(__MINGW32__) |
||
7983 |
extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); |
||
7984 |
namespace Catch { |
||
7985 |
bool isDebuggerActive() { |
||
7986 |
return IsDebuggerPresent() != 0; |
||
7987 |
} |
||
7988 |
} |
||
7989 |
#else |
||
7990 |
namespace Catch { |
||
7991 |
inline bool isDebuggerActive() { return false; } |
||
7992 |
} |
||
7993 |
#endif // Platform |
||
7994 |
|||
7995 |
#ifdef CATCH_PLATFORM_WINDOWS |
||
7996 |
extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); |
||
7997 |
namespace Catch { |
||
7998 |
void writeToDebugConsole( std::string const& text ) { |
||
7999 |
::OutputDebugStringA( text.c_str() ); |
||
8000 |
} |
||
8001 |
} |
||
8002 |
#else |
||
8003 |
namespace Catch { |
||
8004 |
void writeToDebugConsole( std::string const& text ) { |
||
8005 |
// !TBD: Need a version for Mac/ XCode and other IDEs |
||
8006 |
Catch::cout() << text; |
||
8007 |
} |
||
8008 |
} |
||
8009 |
#endif // Platform |
||
8010 |
|||
8011 |
// #included from: catch_tostring.hpp |
||
8012 |
#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED |
||
8013 |
|||
8014 |
namespace Catch { |
||
8015 |
|||
8016 |
namespace Detail { |
||
8017 |
|||
8018 |
3 |
const std::string unprintableString = "{?}"; |
|
8019 |
|||
8020 |
namespace { |
||
8021 |
const int hexThreshold = 255; |
||
8022 |
|||
8023 |
struct Endianness { |
||
8024 |
enum Arch { Big, Little }; |
||
8025 |
|||
8026 |
static Arch which() { |
||
8027 |
union _{ |
||
8028 |
int asInt; |
||
8029 |
char asChar[sizeof (int)]; |
||
8030 |
} u; |
||
8031 |
|||
8032 |
u.asInt = 1; |
||
8033 |
return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; |
||
8034 |
} |
||
8035 |
}; |
||
8036 |
} |
||
8037 |
|||
8038 |
10579 |
std::string rawMemoryToString( const void *object, std::size_t size ) |
|
8039 |
{ |
||
8040 |
// Reverse order for little endian architectures |
||
8041 |
10579 |
int i = 0, end = static_cast<int>( size ), inc = 1; |
|
8042 |
if( Endianness::which() == Endianness::Little ) { |
||
8043 |
10579 |
i = end-1; |
|
8044 |
10579 |
end = inc = -1; |
|
8045 |
} |
||
8046 |
|||
8047 |
10579 |
unsigned char const *bytes = static_cast<unsigned char const *>(object); |
|
8048 |
21158 |
std::ostringstream os; |
|
8049 |
31737 |
os << "0x" << std::setfill('0') << std::hex; |
|
8050 |
✓✓ | 179843 |
for( ; i != end; i += inc ) |
8051 |
253896 |
os << std::setw(2) << static_cast<unsigned>(bytes[i]); |
|
8052 |
21158 |
return os.str(); |
|
8053 |
} |
||
8054 |
} |
||
8055 |
|||
8056 |
164047 |
std::string toString( std::string const& value ) { |
|
8057 |
328094 |
std::string s = value; |
|
8058 |
✓✗✓✗ ✗✓ |
492141 |
if( getCurrentContext().getConfig()->showInvisibles() ) { |
8059 |
for(size_t i = 0; i < s.size(); ++i ) { |
||
8060 |
std::string subs; |
||
8061 |
switch( s[i] ) { |
||
8062 |
case '\n': subs = "\\n"; break; |
||
8063 |
case '\t': subs = "\\t"; break; |
||
8064 |
default: break; |
||
8065 |
} |
||
8066 |
if( !subs.empty() ) { |
||
8067 |
s = s.substr( 0, i ) + subs + s.substr( i+1 ); |
||
8068 |
++i; |
||
8069 |
} |
||
8070 |
} |
||
8071 |
} |
||
8072 |
✓✗✓✗ |
492141 |
return "\"" + s + "\""; |
8073 |
} |
||
8074 |
std::string toString( std::wstring const& value ) { |
||
8075 |
|||
8076 |
std::string s; |
||
8077 |
s.reserve( value.size() ); |
||
8078 |
for(size_t i = 0; i < value.size(); ++i ) |
||
8079 |
s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?'; |
||
8080 |
return Catch::toString( s ); |
||
8081 |
} |
||
8082 |
|||
8083 |
461 |
std::string toString( const char* const value ) { |
|
8084 |
✓✗✓✗ ✓✗✗✗ ✓✗✗✗ |
1383 |
return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); |
8085 |
} |
||
8086 |
|||
8087 |
4 |
std::string toString( char* const value ) { |
|
8088 |
4 |
return Catch::toString( static_cast<const char*>( value ) ); |
|
8089 |
} |
||
8090 |
|||
8091 |
std::string toString( const wchar_t* const value ) |
||
8092 |
{ |
||
8093 |
return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); |
||
8094 |
} |
||
8095 |
|||
8096 |
std::string toString( wchar_t* const value ) |
||
8097 |
{ |
||
8098 |
return Catch::toString( static_cast<const wchar_t*>( value ) ); |
||
8099 |
} |
||
8100 |
|||
8101 |
34114 |
std::string toString( int value ) { |
|
8102 |
68228 |
std::ostringstream oss; |
|
8103 |
✓✗ | 34114 |
oss << value; |
8104 |
✓✓ | 34114 |
if( value > Detail::hexThreshold ) |
8105 |
✓✗✓✗ |
8664 |
oss << " (0x" << std::hex << value << ")"; |
8106 |
68228 |
return oss.str(); |
|
8107 |
} |
||
8108 |
|||
8109 |
1557022 |
std::string toString( unsigned long value ) { |
|
8110 |
3114044 |
std::ostringstream oss; |
|
8111 |
1557022 |
oss << value; |
|
8112 |
✓✓ | 1557022 |
if( value > Detail::hexThreshold ) |
8113 |
✓✗ | 3725253 |
oss << " (0x" << std::hex << value << ")"; |
8114 |
3114044 |
return oss.str(); |
|
8115 |
} |
||
8116 |
|||
8117 |
7806 |
std::string toString( unsigned int value ) { |
|
8118 |
1551081 |
return Catch::toString( static_cast<unsigned long>( value ) ); |
|
8119 |
} |
||
8120 |
|||
8121 |
template<typename T> |
||
8122 |
48 |
std::string fpToString( T value, int precision ) { |
|
8123 |
96 |
std::ostringstream oss; |
|
8124 |
144 |
oss << std::setprecision( precision ) |
|
8125 |
48 |
<< std::fixed |
|
8126 |
<< value; |
||
8127 |
48 |
std::string d = oss.str(); |
|
8128 |
48 |
std::size_t i = d.find_last_not_of( '0' ); |
|
8129 |
✓✗✗✓ ✓✗✓✗ ✗✓✓✗ |
48 |
if( i != std::string::npos && i != d.size()-1 ) { |
8130 |
✓✓✓✓ |
48 |
if( d[i] == '.' ) |
8131 |
36 |
i++; |
|
8132 |
✓✗✓✗ |
96 |
d = d.substr( 0, i+1 ); |
8133 |
} |
||
8134 |
48 |
return d; |
|
8135 |
} |
||
8136 |
|||
8137 |
12 |
std::string toString( const double value ) { |
|
8138 |
✗✗ | 12 |
return fpToString( value, 10 ); |
8139 |
} |
||
8140 |
36 |
std::string toString( const float value ) { |
|
8141 |
✓✗ | 72 |
return fpToString( value, 5 ) + "f"; |
8142 |
} |
||
8143 |
|||
8144 |
161707 |
std::string toString( bool value ) { |
|
8145 |
✓✓ | 485121 |
return value ? "true" : "false"; |
8146 |
} |
||
8147 |
|||
8148 |
2469929 |
std::string toString( char value ) { |
|
8149 |
2469929 |
return value < ' ' |
|
8150 |
? toString( static_cast<unsigned int>( value ) ) |
||
8151 |
✓✓ | 4939858 |
: Detail::makeString( value ); |
8152 |
} |
||
8153 |
|||
8154 |
29 |
std::string toString( signed char value ) { |
|
8155 |
29 |
return toString( static_cast<char>( value ) ); |
|
8156 |
} |
||
8157 |
|||
8158 |
144 |
std::string toString( unsigned char value ) { |
|
8159 |
144 |
return toString( static_cast<char>( value ) ); |
|
8160 |
} |
||
8161 |
|||
8162 |
#ifdef CATCH_CONFIG_CPP11_LONG_LONG |
||
8163 |
std::string toString( long long value ) { |
||
8164 |
std::ostringstream oss; |
||
8165 |
oss << value; |
||
8166 |
if( value > Detail::hexThreshold ) |
||
8167 |
oss << " (0x" << std::hex << value << ")"; |
||
8168 |
return oss.str(); |
||
8169 |
} |
||
8170 |
std::string toString( unsigned long long value ) { |
||
8171 |
std::ostringstream oss; |
||
8172 |
oss << value; |
||
8173 |
if( value > Detail::hexThreshold ) |
||
8174 |
oss << " (0x" << std::hex << value << ")"; |
||
8175 |
return oss.str(); |
||
8176 |
} |
||
8177 |
#endif |
||
8178 |
|||
8179 |
#ifdef CATCH_CONFIG_CPP11_NULLPTR |
||
8180 |
10395 |
std::string toString( std::nullptr_t ) { |
|
8181 |
31185 |
return "nullptr"; |
|
8182 |
} |
||
8183 |
#endif |
||
8184 |
|||
8185 |
#ifdef __OBJC__ |
||
8186 |
std::string toString( NSString const * const& nsstring ) { |
||
8187 |
if( !nsstring ) |
||
8188 |
return "nil"; |
||
8189 |
return "@" + toString([nsstring UTF8String]); |
||
8190 |
} |
||
8191 |
std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { |
||
8192 |
if( !nsstring ) |
||
8193 |
return "nil"; |
||
8194 |
return "@" + toString([nsstring UTF8String]); |
||
8195 |
} |
||
8196 |
std::string toString( NSObject* const& nsObject ) { |
||
8197 |
return toString( [nsObject description] ); |
||
8198 |
} |
||
8199 |
#endif |
||
8200 |
|||
8201 |
} // end namespace Catch |
||
8202 |
|||
8203 |
// #included from: catch_result_builder.hpp |
||
8204 |
#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED |
||
8205 |
|||
8206 |
namespace Catch { |
||
8207 |
|||
8208 |
1432923 |
std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { |
|
8209 |
✓✗ | 1432954 |
return secondArg.empty() || secondArg == "\"\"" |
8210 |
✓✓ | 1432923 |
? capturedExpression |
8211 |
✗✗✗✗ ✗✓✗✗ |
1432923 |
: capturedExpression + ", " + secondArg; |
8212 |
} |
||
8213 |
1432923 |
ResultBuilder::ResultBuilder( char const* macroName, |
|
8214 |
SourceLineInfo const& lineInfo, |
||
8215 |
char const* capturedExpression, |
||
8216 |
ResultDisposition::Flags resultDisposition, |
||
8217 |
1432923 |
char const* secondArg ) |
|
8218 |
✓✗✓✗ |
11463384 |
: m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), |
8219 |
m_shouldDebugBreak( false ), |
||
8220 |
✓✗✓✗ |
11463384 |
m_shouldThrow( false ) |
8221 |
1432923 |
{} |
|
8222 |
|||
8223 |
ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { |
||
8224 |
m_data.resultType = result; |
||
8225 |
return *this; |
||
8226 |
} |
||
8227 |
1432892 |
ResultBuilder& ResultBuilder::setResultType( bool result ) { |
|
8228 |
✓✓ | 1432892 |
m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; |
8229 |
1432892 |
return *this; |
|
8230 |
} |
||
8231 |
1432892 |
ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { |
|
8232 |
2865784 |
m_exprComponents.lhs = lhs; |
|
8233 |
1432892 |
return *this; |
|
8234 |
} |
||
8235 |
1432423 |
ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { |
|
8236 |
2864846 |
m_exprComponents.rhs = rhs; |
|
8237 |
1432423 |
return *this; |
|
8238 |
} |
||
8239 |
1432423 |
ResultBuilder& ResultBuilder::setOp( std::string const& op ) { |
|
8240 |
2864846 |
m_exprComponents.op = op; |
|
8241 |
1432423 |
return *this; |
|
8242 |
} |
||
8243 |
|||
8244 |
1432892 |
void ResultBuilder::endExpression() { |
|
8245 |
2865784 |
m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); |
|
8246 |
1432892 |
captureExpression(); |
|
8247 |
1432892 |
} |
|
8248 |
|||
8249 |
void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { |
||
8250 |
m_assertionInfo.resultDisposition = resultDisposition; |
||
8251 |
m_stream.oss << Catch::translateActiveException(); |
||
8252 |
captureResult( ResultWas::ThrewException ); |
||
8253 |
} |
||
8254 |
|||
8255 |
void ResultBuilder::captureResult( ResultWas::OfType resultType ) { |
||
8256 |
setResultType( resultType ); |
||
8257 |
captureExpression(); |
||
8258 |
} |
||
8259 |
31 |
void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { |
|
8260 |
✓✗ | 31 |
if( expectedMessage.empty() ) |
8261 |
✓✗ | 62 |
captureExpectedException( Matchers::Impl::Generic::AllOf<std::string>() ); |
8262 |
else |
||
8263 |
captureExpectedException( Matchers::Equals( expectedMessage ) ); |
||
8264 |
31 |
} |
|
8265 |
|||
8266 |
31 |
void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ) { |
|
8267 |
|||
8268 |
✗✓ | 31 |
assert( m_exprComponents.testFalse == false ); |
8269 |
62 |
AssertionResultData data = m_data; |
|
8270 |
31 |
data.resultType = ResultWas::Ok; |
|
8271 |
62 |
data.reconstructedExpression = m_assertionInfo.capturedExpression; |
|
8272 |
|||
8273 |
✓✗ | 62 |
std::string actualMessage = Catch::translateActiveException(); |
8274 |
✓✗✗✓ |
31 |
if( !matcher.match( actualMessage ) ) { |
8275 |
data.resultType = ResultWas::ExpressionFailed; |
||
8276 |
data.reconstructedExpression = actualMessage; |
||
8277 |
} |
||
8278 |
✓✗ | 62 |
AssertionResult result( m_assertionInfo, data ); |
8279 |
✓✗ | 31 |
handleResult( result ); |
8280 |
31 |
} |
|
8281 |
|||
8282 |
1432892 |
void ResultBuilder::captureExpression() { |
|
8283 |
2865784 |
AssertionResult result = build(); |
|
8284 |
✓✗ | 1432892 |
handleResult( result ); |
8285 |
1432892 |
} |
|
8286 |
1432923 |
void ResultBuilder::handleResult( AssertionResult const& result ) |
|
8287 |
{ |
||
8288 |
1432923 |
getResultCapture().assertionEnded( result ); |
|
8289 |
|||
8290 |
✗✓ | 1432923 |
if( !result.isOk() ) { |
8291 |
if( getCurrentContext().getConfig()->shouldDebugBreak() ) |
||
8292 |
m_shouldDebugBreak = true; |
||
8293 |
if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) |
||
8294 |
m_shouldThrow = true; |
||
8295 |
} |
||
8296 |
1432923 |
} |
|
8297 |
1432923 |
void ResultBuilder::react() { |
|
8298 |
✗✓ | 1432923 |
if( m_shouldThrow ) |
8299 |
throw Catch::TestFailureException(); |
||
8300 |
1432923 |
} |
|
8301 |
|||
8302 |
1432923 |
bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } |
|
8303 |
✓✗ | 124 |
bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } |
8304 |
|||
8305 |
1432892 |
AssertionResult ResultBuilder::build() const |
|
8306 |
{ |
||
8307 |
✗✓ | 1432892 |
assert( m_data.resultType != ResultWas::Unknown ); |
8308 |
|||
8309 |
2865784 |
AssertionResultData data = m_data; |
|
8310 |
|||
8311 |
// Flip bool results if testFalse is set |
||
8312 |
✓✓ | 1432892 |
if( m_exprComponents.testFalse ) { |
8313 |
✗✓ | 15 |
if( data.resultType == ResultWas::Ok ) |
8314 |
data.resultType = ResultWas::ExpressionFailed; |
||
8315 |
✓✗ | 15 |
else if( data.resultType == ResultWas::ExpressionFailed ) |
8316 |
15 |
data.resultType = ResultWas::Ok; |
|
8317 |
} |
||
8318 |
|||
8319 |
4298676 |
data.message = m_stream.oss.str(); |
|
8320 |
✓✗ | 2865784 |
data.reconstructedExpression = reconstructExpression(); |
8321 |
✓✓ | 1432892 |
if( m_exprComponents.testFalse ) { |
8322 |
✓✓ | 30 |
if( m_exprComponents.op == "" ) |
8323 |
✓✗ | 18 |
data.reconstructedExpression = "!" + data.reconstructedExpression; |
8324 |
else |
||
8325 |
✓✗✓✗ |
18 |
data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; |
8326 |
} |
||
8327 |
✓✗ | 2865784 |
return AssertionResult( m_assertionInfo, data ); |
8328 |
} |
||
8329 |
1432892 |
std::string ResultBuilder::reconstructExpression() const { |
|
8330 |
✓✓ | 2865784 |
if( m_exprComponents.op == "" ) |
8331 |
✗✓ | 1407 |
return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; |
8332 |
✗✓ | 2864846 |
else if( m_exprComponents.op == "matches" ) |
8333 |
return m_exprComponents.lhs + " " + m_exprComponents.rhs; |
||
8334 |
✓✗ | 2864846 |
else if( m_exprComponents.op != "!" ) { |
8335 |
✓✗✓✓ |
3677326 |
if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && |
8336 |
✓✓✗✓ |
3057383 |
m_exprComponents.lhs.find("\n") == std::string::npos && |
8337 |
1624960 |
m_exprComponents.rhs.find("\n") == std::string::npos ) |
|
8338 |
✓✗✓✗ ✓✗ |
3249920 |
return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; |
8339 |
else |
||
8340 |
✓✗✓✗ ✓✗ |
2479772 |
return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; |
8341 |
} |
||
8342 |
else |
||
8343 |
return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; |
||
8344 |
} |
||
8345 |
|||
8346 |
} // end namespace Catch |
||
8347 |
|||
8348 |
// #included from: catch_tag_alias_registry.hpp |
||
8349 |
#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED |
||
8350 |
|||
8351 |
// #included from: catch_tag_alias_registry.h |
||
8352 |
#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED |
||
8353 |
|||
8354 |
#include <map> |
||
8355 |
|||
8356 |
namespace Catch { |
||
8357 |
|||
8358 |
2 |
class TagAliasRegistry : public ITagAliasRegistry { |
|
8359 |
public: |
||
8360 |
virtual ~TagAliasRegistry(); |
||
8361 |
virtual Option<TagAlias> find( std::string const& alias ) const; |
||
8362 |
virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; |
||
8363 |
void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); |
||
8364 |
static TagAliasRegistry& get(); |
||
8365 |
|||
8366 |
private: |
||
8367 |
std::map<std::string, TagAlias> m_registry; |
||
8368 |
}; |
||
8369 |
|||
8370 |
} // end namespace Catch |
||
8371 |
|||
8372 |
#include <map> |
||
8373 |
#include <iostream> |
||
8374 |
|||
8375 |
namespace Catch { |
||
8376 |
|||
8377 |
2 |
TagAliasRegistry::~TagAliasRegistry() {} |
|
8378 |
|||
8379 |
Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const { |
||
8380 |
std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias ); |
||
8381 |
if( it != m_registry.end() ) |
||
8382 |
return it->second; |
||
8383 |
else |
||
8384 |
return Option<TagAlias>(); |
||
8385 |
} |
||
8386 |
|||
8387 |
1 |
std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { |
|
8388 |
1 |
std::string expandedTestSpec = unexpandedTestSpec; |
|
8389 |
✗✓ | 3 |
for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); |
8390 |
it != itEnd; |
||
8391 |
++it ) { |
||
8392 |
std::size_t pos = expandedTestSpec.find( it->first ); |
||
8393 |
if( pos != std::string::npos ) { |
||
8394 |
expandedTestSpec = expandedTestSpec.substr( 0, pos ) + |
||
8395 |
it->second.tag + |
||
8396 |
expandedTestSpec.substr( pos + it->first.size() ); |
||
8397 |
} |
||
8398 |
} |
||
8399 |
1 |
return expandedTestSpec; |
|
8400 |
} |
||
8401 |
|||
8402 |
void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { |
||
8403 |
|||
8404 |
if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { |
||
8405 |
std::ostringstream oss; |
||
8406 |
oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; |
||
8407 |
throw std::domain_error( oss.str().c_str() ); |
||
8408 |
} |
||
8409 |
if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { |
||
8410 |
std::ostringstream oss; |
||
8411 |
oss << "error: tag alias, \"" << alias << "\" already registered.\n" |
||
8412 |
<< "\tFirst seen at " << find(alias)->lineInfo << "\n" |
||
8413 |
<< "\tRedefined at " << lineInfo; |
||
8414 |
throw std::domain_error( oss.str().c_str() ); |
||
8415 |
} |
||
8416 |
} |
||
8417 |
|||
8418 |
1 |
TagAliasRegistry& TagAliasRegistry::get() { |
|
8419 |
✓✗✓✗ |
2 |
static TagAliasRegistry instance; |
8420 |
1 |
return instance; |
|
8421 |
|||
8422 |
} |
||
8423 |
|||
8424 |
ITagAliasRegistry::~ITagAliasRegistry() {} |
||
8425 |
1 |
ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } |
|
8426 |
|||
8427 |
RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { |
||
8428 |
try { |
||
8429 |
TagAliasRegistry::get().add( alias, tag, lineInfo ); |
||
8430 |
} |
||
8431 |
catch( std::exception& ex ) { |
||
8432 |
Colour colourGuard( Colour::Red ); |
||
8433 |
Catch::cerr() << ex.what() << std::endl; |
||
8434 |
exit(1); |
||
8435 |
} |
||
8436 |
} |
||
8437 |
|||
8438 |
} // end namespace Catch |
||
8439 |
|||
8440 |
// #included from: ../reporters/catch_reporter_multi.hpp |
||
8441 |
#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED |
||
8442 |
|||
8443 |
namespace Catch { |
||
8444 |
|||
8445 |
class MultipleReporters : public SharedImpl<IStreamingReporter> { |
||
8446 |
typedef std::vector<Ptr<IStreamingReporter> > Reporters; |
||
8447 |
Reporters m_reporters; |
||
8448 |
|||
8449 |
public: |
||
8450 |
void add( Ptr<IStreamingReporter> const& reporter ) { |
||
8451 |
m_reporters.push_back( reporter ); |
||
8452 |
} |
||
8453 |
|||
8454 |
public: // IStreamingReporter |
||
8455 |
|||
8456 |
virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { |
||
8457 |
return m_reporters[0]->getPreferences(); |
||
8458 |
} |
||
8459 |
|||
8460 |
virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { |
||
8461 |
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); |
||
8462 |
it != itEnd; |
||
8463 |
++it ) |
||
8464 |
(*it)->noMatchingTestCases( spec ); |
||
8465 |
} |
||
8466 |
|||
8467 |
virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { |
||
8468 |
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); |
||
8469 |
it != itEnd; |
||
8470 |
++it ) |
||
8471 |
(*it)->testRunStarting( testRunInfo ); |
||
8472 |
} |
||
8473 |
|||
8474 |
virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { |
||
8475 |
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); |
||
8476 |
it != itEnd; |
||
8477 |
++it ) |
||
8478 |
(*it)->testGroupStarting( groupInfo ); |
||
8479 |
} |
||
8480 |
|||
8481 |
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { |
||
8482 |
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); |
||
8483 |
it != itEnd; |
||
8484 |
++it ) |
||
8485 |
(*it)->testCaseStarting( testInfo ); |
||
8486 |
} |
||
8487 |
|||
8488 |
virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { |
||
8489 |
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); |
||
8490 |
it != itEnd; |
||
8491 |
++it ) |
||
8492 |
(*it)->sectionStarting( sectionInfo ); |
||
8493 |
} |
||
8494 |
|||
8495 |
virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { |
||
8496 |
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); |
||
8497 |
it != itEnd; |
||
8498 |
++it ) |
||
8499 |
(*it)->assertionStarting( assertionInfo ); |
||
8500 |
} |
||
8501 |
|||
8502 |
// The return value indicates if the messages buffer should be cleared: |
||
8503 |
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { |
||
8504 |
bool clearBuffer = false; |
||
8505 |
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); |
||
8506 |
it != itEnd; |
||
8507 |
++it ) |
||
8508 |
clearBuffer |= (*it)->assertionEnded( assertionStats ); |
||
8509 |
return clearBuffer; |
||
8510 |
} |
||
8511 |
|||
8512 |
virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { |
||
8513 |
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); |
||
8514 |
it != itEnd; |
||
8515 |
++it ) |
||
8516 |
(*it)->sectionEnded( sectionStats ); |
||
8517 |
} |
||
8518 |
|||
8519 |
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { |
||
8520 |
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); |
||
8521 |
it != itEnd; |
||
8522 |
++it ) |
||
8523 |
(*it)->testCaseEnded( testCaseStats ); |
||
8524 |
} |
||
8525 |
|||
8526 |
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { |
||
8527 |
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); |
||
8528 |
it != itEnd; |
||
8529 |
++it ) |
||
8530 |
(*it)->testGroupEnded( testGroupStats ); |
||
8531 |
} |
||
8532 |
|||
8533 |
virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { |
||
8534 |
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); |
||
8535 |
it != itEnd; |
||
8536 |
++it ) |
||
8537 |
(*it)->testRunEnded( testRunStats ); |
||
8538 |
} |
||
8539 |
|||
8540 |
virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { |
||
8541 |
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); |
||
8542 |
it != itEnd; |
||
8543 |
++it ) |
||
8544 |
(*it)->skipTest( testInfo ); |
||
8545 |
} |
||
8546 |
|||
8547 |
virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { |
||
8548 |
return this; |
||
8549 |
} |
||
8550 |
|||
8551 |
}; |
||
8552 |
|||
8553 |
1 |
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) { |
|
8554 |
1 |
Ptr<IStreamingReporter> resultingReporter; |
|
8555 |
|||
8556 |
✗✓ | 1 |
if( existingReporter ) { |
8557 |
MultipleReporters* multi = existingReporter->tryAsMulti(); |
||
8558 |
if( !multi ) { |
||
8559 |
multi = new MultipleReporters; |
||
8560 |
resultingReporter = Ptr<IStreamingReporter>( multi ); |
||
8561 |
if( existingReporter ) |
||
8562 |
multi->add( existingReporter ); |
||
8563 |
} |
||
8564 |
else |
||
8565 |
resultingReporter = existingReporter; |
||
8566 |
multi->add( additionalReporter ); |
||
8567 |
} |
||
8568 |
else |
||
8569 |
✓✗ | 1 |
resultingReporter = additionalReporter; |
8570 |
|||
8571 |
1 |
return resultingReporter; |
|
8572 |
} |
||
8573 |
|||
8574 |
} // end namespace Catch |
||
8575 |
|||
8576 |
// #included from: ../reporters/catch_reporter_xml.hpp |
||
8577 |
#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED |
||
8578 |
|||
8579 |
// #included from: catch_reporter_bases.hpp |
||
8580 |
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED |
||
8581 |
|||
8582 |
#include <cstring> |
||
8583 |
|||
8584 |
namespace Catch { |
||
8585 |
|||
8586 |
struct StreamingReporterBase : SharedImpl<IStreamingReporter> { |
||
8587 |
|||
8588 |
StreamingReporterBase( ReporterConfig const& _config ) |
||
8589 |
1 |
: m_config( _config.fullConfig() ), |
|
8590 |
8 |
stream( _config.stream() ) |
|
8591 |
{ |
||
8592 |
m_reporterPrefs.shouldRedirectStdOut = false; |
||
8593 |
} |
||
8594 |
|||
8595 |
745 |
virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { |
|
8596 |
745 |
return m_reporterPrefs; |
|
8597 |
} |
||
8598 |
|||
8599 |
virtual ~StreamingReporterBase() CATCH_OVERRIDE; |
||
8600 |
|||
8601 |
virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} |
||
8602 |
|||
8603 |
1 |
virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { |
|
8604 |
2 |
currentTestRunInfo = _testRunInfo; |
|
8605 |
1 |
} |
|
8606 |
1 |
virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { |
|
8607 |
2 |
currentGroupInfo = _groupInfo; |
|
8608 |
1 |
} |
|
8609 |
|||
8610 |
394 |
virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { |
|
8611 |
788 |
currentTestCaseInfo = _testInfo; |
|
8612 |
394 |
} |
|
8613 |
virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { |
||
8614 |
1145 |
m_sectionStack.push_back( _sectionInfo ); |
|
8615 |
} |
||
8616 |
|||
8617 |
virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { |
||
8618 |
1145 |
m_sectionStack.pop_back(); |
|
8619 |
} |
||
8620 |
virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { |
||
8621 |
788 |
currentTestCaseInfo.reset(); |
|
8622 |
} |
||
8623 |
virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { |
||
8624 |
2 |
currentGroupInfo.reset(); |
|
8625 |
} |
||
8626 |
1 |
virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { |
|
8627 |
2 |
currentTestCaseInfo.reset(); |
|
8628 |
2 |
currentGroupInfo.reset(); |
|
8629 |
2 |
currentTestRunInfo.reset(); |
|
8630 |
1 |
} |
|
8631 |
|||
8632 |
virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { |
||
8633 |
// Don't do anything with this by default. |
||
8634 |
// It can optionally be overridden in the derived class. |
||
8635 |
} |
||
8636 |
|||
8637 |
Ptr<IConfig const> m_config; |
||
8638 |
std::ostream& stream; |
||
8639 |
|||
8640 |
LazyStat<TestRunInfo> currentTestRunInfo; |
||
8641 |
LazyStat<GroupInfo> currentGroupInfo; |
||
8642 |
LazyStat<TestCaseInfo> currentTestCaseInfo; |
||
8643 |
|||
8644 |
std::vector<SectionInfo> m_sectionStack; |
||
8645 |
ReporterPreferences m_reporterPrefs; |
||
8646 |
}; |
||
8647 |
|||
8648 |
struct CumulativeReporterBase : SharedImpl<IStreamingReporter> { |
||
8649 |
template<typename T, typename ChildNodeT> |
||
8650 |
struct Node : SharedImpl<> { |
||
8651 |
explicit Node( T const& _value ) : value( _value ) {} |
||
8652 |
virtual ~Node() {} |
||
8653 |
|||
8654 |
typedef std::vector<Ptr<ChildNodeT> > ChildNodes; |
||
8655 |
T value; |
||
8656 |
ChildNodes children; |
||
8657 |
}; |
||
8658 |
struct SectionNode : SharedImpl<> { |
||
8659 |
explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} |
||
8660 |
virtual ~SectionNode(); |
||
8661 |
|||
8662 |
bool operator == ( SectionNode const& other ) const { |
||
8663 |
return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; |
||
8664 |
} |
||
8665 |
bool operator == ( Ptr<SectionNode> const& other ) const { |
||
8666 |
return operator==( *other ); |
||
8667 |
} |
||
8668 |
|||
8669 |
SectionStats stats; |
||
8670 |
typedef std::vector<Ptr<SectionNode> > ChildSections; |
||
8671 |
typedef std::vector<AssertionStats> Assertions; |
||
8672 |
ChildSections childSections; |
||
8673 |
Assertions assertions; |
||
8674 |
std::string stdOut; |
||
8675 |
std::string stdErr; |
||
8676 |
}; |
||
8677 |
|||
8678 |
struct BySectionInfo { |
||
8679 |
BySectionInfo( SectionInfo const& other ) : m_other( other ) {} |
||
8680 |
BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} |
||
8681 |
bool operator() ( Ptr<SectionNode> const& node ) const { |
||
8682 |
return node->stats.sectionInfo.lineInfo == m_other.lineInfo; |
||
8683 |
} |
||
8684 |
private: |
||
8685 |
void operator=( BySectionInfo const& ); |
||
8686 |
SectionInfo const& m_other; |
||
8687 |
}; |
||
8688 |
|||
8689 |
typedef Node<TestCaseStats, SectionNode> TestCaseNode; |
||
8690 |
typedef Node<TestGroupStats, TestCaseNode> TestGroupNode; |
||
8691 |
typedef Node<TestRunStats, TestGroupNode> TestRunNode; |
||
8692 |
|||
8693 |
CumulativeReporterBase( ReporterConfig const& _config ) |
||
8694 |
: m_config( _config.fullConfig() ), |
||
8695 |
stream( _config.stream() ) |
||
8696 |
{ |
||
8697 |
m_reporterPrefs.shouldRedirectStdOut = false; |
||
8698 |
} |
||
8699 |
~CumulativeReporterBase(); |
||
8700 |
|||
8701 |
virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { |
||
8702 |
return m_reporterPrefs; |
||
8703 |
} |
||
8704 |
|||
8705 |
virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} |
||
8706 |
virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} |
||
8707 |
|||
8708 |
virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} |
||
8709 |
|||
8710 |
virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { |
||
8711 |
SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); |
||
8712 |
Ptr<SectionNode> node; |
||
8713 |
if( m_sectionStack.empty() ) { |
||
8714 |
if( !m_rootSection ) |
||
8715 |
m_rootSection = new SectionNode( incompleteStats ); |
||
8716 |
node = m_rootSection; |
||
8717 |
} |
||
8718 |
else { |
||
8719 |
SectionNode& parentNode = *m_sectionStack.back(); |
||
8720 |
SectionNode::ChildSections::const_iterator it = |
||
8721 |
std::find_if( parentNode.childSections.begin(), |
||
8722 |
parentNode.childSections.end(), |
||
8723 |
BySectionInfo( sectionInfo ) ); |
||
8724 |
if( it == parentNode.childSections.end() ) { |
||
8725 |
node = new SectionNode( incompleteStats ); |
||
8726 |
parentNode.childSections.push_back( node ); |
||
8727 |
} |
||
8728 |
else |
||
8729 |
node = *it; |
||
8730 |
} |
||
8731 |
m_sectionStack.push_back( node ); |
||
8732 |
m_deepestSection = node; |
||
8733 |
} |
||
8734 |
|||
8735 |
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} |
||
8736 |
|||
8737 |
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { |
||
8738 |
assert( !m_sectionStack.empty() ); |
||
8739 |
SectionNode& sectionNode = *m_sectionStack.back(); |
||
8740 |
sectionNode.assertions.push_back( assertionStats ); |
||
8741 |
return true; |
||
8742 |
} |
||
8743 |
virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { |
||
8744 |
assert( !m_sectionStack.empty() ); |
||
8745 |
SectionNode& node = *m_sectionStack.back(); |
||
8746 |
node.stats = sectionStats; |
||
8747 |
m_sectionStack.pop_back(); |
||
8748 |
} |
||
8749 |
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { |
||
8750 |
Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats ); |
||
8751 |
assert( m_sectionStack.size() == 0 ); |
||
8752 |
node->children.push_back( m_rootSection ); |
||
8753 |
m_testCases.push_back( node ); |
||
8754 |
m_rootSection.reset(); |
||
8755 |
|||
8756 |
assert( m_deepestSection ); |
||
8757 |
m_deepestSection->stdOut = testCaseStats.stdOut; |
||
8758 |
m_deepestSection->stdErr = testCaseStats.stdErr; |
||
8759 |
} |
||
8760 |
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { |
||
8761 |
Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats ); |
||
8762 |
node->children.swap( m_testCases ); |
||
8763 |
m_testGroups.push_back( node ); |
||
8764 |
} |
||
8765 |
virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { |
||
8766 |
Ptr<TestRunNode> node = new TestRunNode( testRunStats ); |
||
8767 |
node->children.swap( m_testGroups ); |
||
8768 |
m_testRuns.push_back( node ); |
||
8769 |
testRunEndedCumulative(); |
||
8770 |
} |
||
8771 |
virtual void testRunEndedCumulative() = 0; |
||
8772 |
|||
8773 |
virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} |
||
8774 |
|||
8775 |
Ptr<IConfig const> m_config; |
||
8776 |
std::ostream& stream; |
||
8777 |
std::vector<AssertionStats> m_assertions; |
||
8778 |
std::vector<std::vector<Ptr<SectionNode> > > m_sections; |
||
8779 |
std::vector<Ptr<TestCaseNode> > m_testCases; |
||
8780 |
std::vector<Ptr<TestGroupNode> > m_testGroups; |
||
8781 |
|||
8782 |
std::vector<Ptr<TestRunNode> > m_testRuns; |
||
8783 |
|||
8784 |
Ptr<SectionNode> m_rootSection; |
||
8785 |
Ptr<SectionNode> m_deepestSection; |
||
8786 |
std::vector<Ptr<SectionNode> > m_sectionStack; |
||
8787 |
ReporterPreferences m_reporterPrefs; |
||
8788 |
|||
8789 |
}; |
||
8790 |
|||
8791 |
template<char C> |
||
8792 |
char const* getLineOfChars() { |
||
8793 |
static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; |
||
8794 |
if( !*line ) { |
||
8795 |
memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); |
||
8796 |
line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; |
||
8797 |
} |
||
8798 |
return line; |
||
8799 |
} |
||
8800 |
|||
8801 |
struct TestEventListenerBase : StreamingReporterBase { |
||
8802 |
TestEventListenerBase( ReporterConfig const& _config ) |
||
8803 |
: StreamingReporterBase( _config ) |
||
8804 |
{} |
||
8805 |
|||
8806 |
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} |
||
8807 |
virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { |
||
8808 |
return false; |
||
8809 |
} |
||
8810 |
}; |
||
8811 |
|||
8812 |
} // end namespace Catch |
||
8813 |
|||
8814 |
// #included from: ../internal/catch_reporter_registrars.hpp |
||
8815 |
#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED |
||
8816 |
|||
8817 |
namespace Catch { |
||
8818 |
|||
8819 |
template<typename T> |
||
8820 |
class LegacyReporterRegistrar { |
||
8821 |
|||
8822 |
class ReporterFactory : public IReporterFactory { |
||
8823 |
virtual IStreamingReporter* create( ReporterConfig const& config ) const { |
||
8824 |
return new LegacyReporterAdapter( new T( config ) ); |
||
8825 |
} |
||
8826 |
|||
8827 |
virtual std::string getDescription() const { |
||
8828 |
return T::getDescription(); |
||
8829 |
} |
||
8830 |
}; |
||
8831 |
|||
8832 |
public: |
||
8833 |
|||
8834 |
LegacyReporterRegistrar( std::string const& name ) { |
||
8835 |
getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); |
||
8836 |
} |
||
8837 |
}; |
||
8838 |
|||
8839 |
template<typename T> |
||
8840 |
class ReporterRegistrar { |
||
8841 |
|||
8842 |
16 |
class ReporterFactory : public SharedImpl<IReporterFactory> { |
|
8843 |
|||
8844 |
// *** Please Note ***: |
||
8845 |
// - If you end up here looking at a compiler error because it's trying to register |
||
8846 |
// your custom reporter class be aware that the native reporter interface has changed |
||
8847 |
// to IStreamingReporter. The "legacy" interface, IReporter, is still supported via |
||
8848 |
// an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. |
||
8849 |
// However please consider updating to the new interface as the old one is now |
||
8850 |
// deprecated and will probably be removed quite soon! |
||
8851 |
// Please contact me via github if you have any questions at all about this. |
||
8852 |
// In fact, ideally, please contact me anyway to let me know you've hit this - as I have |
||
8853 |
// no idea who is actually using custom reporters at all (possibly no-one!). |
||
8854 |
// The new interface is designed to minimise exposure to interface changes in the future. |
||
8855 |
1 |
virtual IStreamingReporter* create( ReporterConfig const& config ) const { |
|
8856 |
✗✗✗✗ |
2 |
return new T( config ); |
8857 |
} |
||
8858 |
|||
8859 |
virtual std::string getDescription() const { |
||
8860 |
return T::getDescription(); |
||
8861 |
} |
||
8862 |
}; |
||
8863 |
|||
8864 |
public: |
||
8865 |
|||
8866 |
4 |
ReporterRegistrar( std::string const& name ) { |
|
8867 |
✓✗✓✗ ✓✗✓✗ |
12 |
getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); |
8868 |
4 |
} |
|
8869 |
}; |
||
8870 |
|||
8871 |
template<typename T> |
||
8872 |
class ListenerRegistrar { |
||
8873 |
|||
8874 |
class ListenerFactory : public SharedImpl<IReporterFactory> { |
||
8875 |
|||
8876 |
virtual IStreamingReporter* create( ReporterConfig const& config ) const { |
||
8877 |
return new T( config ); |
||
8878 |
} |
||
8879 |
virtual std::string getDescription() const { |
||
8880 |
return ""; |
||
8881 |
} |
||
8882 |
}; |
||
8883 |
|||
8884 |
public: |
||
8885 |
|||
8886 |
ListenerRegistrar() { |
||
8887 |
getMutableRegistryHub().registerListener( new ListenerFactory() ); |
||
8888 |
} |
||
8889 |
}; |
||
8890 |
} |
||
8891 |
|||
8892 |
#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ |
||
8893 |
namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } |
||
8894 |
|||
8895 |
#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ |
||
8896 |
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } |
||
8897 |
|||
8898 |
#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ |
||
8899 |
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } |
||
8900 |
|||
8901 |
// #included from: ../internal/catch_xmlwriter.hpp |
||
8902 |
#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED |
||
8903 |
|||
8904 |
#include <sstream> |
||
8905 |
#include <string> |
||
8906 |
#include <vector> |
||
8907 |
#include <iomanip> |
||
8908 |
|||
8909 |
namespace Catch { |
||
8910 |
|||
8911 |
class XmlEncode { |
||
8912 |
public: |
||
8913 |
enum ForWhat { ForTextNodes, ForAttributes }; |
||
8914 |
|||
8915 |
XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) |
||
8916 |
: m_str( str ), |
||
8917 |
m_forWhat( forWhat ) |
||
8918 |
{} |
||
8919 |
|||
8920 |
void encodeTo( std::ostream& os ) const { |
||
8921 |
|||
8922 |
// Apostrophe escaping not necessary if we always use " to write attributes |
||
8923 |
// (see: http://www.w3.org/TR/xml/#syntax) |
||
8924 |
|||
8925 |
for( std::size_t i = 0; i < m_str.size(); ++ i ) { |
||
8926 |
char c = m_str[i]; |
||
8927 |
switch( c ) { |
||
8928 |
case '<': os << "<"; break; |
||
8929 |
case '&': os << "&"; break; |
||
8930 |
|||
8931 |
case '>': |
||
8932 |
// See: http://www.w3.org/TR/xml/#syntax |
||
8933 |
if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) |
||
8934 |
os << ">"; |
||
8935 |
else |
||
8936 |
os << c; |
||
8937 |
break; |
||
8938 |
|||
8939 |
case '\"': |
||
8940 |
if( m_forWhat == ForAttributes ) |
||
8941 |
os << """; |
||
8942 |
else |
||
8943 |
os << c; |
||
8944 |
break; |
||
8945 |
|||
8946 |
default: |
||
8947 |
// Escape control chars - based on contribution by @espenalb in PR #465 |
||
8948 |
if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) |
||
8949 |
os << "&#x" << std::uppercase << std::hex << static_cast<int>( c ); |
||
8950 |
else |
||
8951 |
os << c; |
||
8952 |
} |
||
8953 |
} |
||
8954 |
} |
||
8955 |
|||
8956 |
friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { |
||
8957 |
xmlEncode.encodeTo( os ); |
||
8958 |
return os; |
||
8959 |
} |
||
8960 |
|||
8961 |
private: |
||
8962 |
std::string m_str; |
||
8963 |
ForWhat m_forWhat; |
||
8964 |
}; |
||
8965 |
|||
8966 |
class XmlWriter { |
||
8967 |
public: |
||
8968 |
|||
8969 |
class ScopedElement { |
||
8970 |
public: |
||
8971 |
ScopedElement( XmlWriter* writer ) |
||
8972 |
: m_writer( writer ) |
||
8973 |
{} |
||
8974 |
|||
8975 |
ScopedElement( ScopedElement const& other ) |
||
8976 |
: m_writer( other.m_writer ){ |
||
8977 |
other.m_writer = CATCH_NULL; |
||
8978 |
} |
||
8979 |
|||
8980 |
~ScopedElement() { |
||
8981 |
if( m_writer ) |
||
8982 |
m_writer->endElement(); |
||
8983 |
} |
||
8984 |
|||
8985 |
ScopedElement& writeText( std::string const& text, bool indent = true ) { |
||
8986 |
m_writer->writeText( text, indent ); |
||
8987 |
return *this; |
||
8988 |
} |
||
8989 |
|||
8990 |
template<typename T> |
||
8991 |
ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { |
||
8992 |
m_writer->writeAttribute( name, attribute ); |
||
8993 |
return *this; |
||
8994 |
} |
||
8995 |
|||
8996 |
private: |
||
8997 |
mutable XmlWriter* m_writer; |
||
8998 |
}; |
||
8999 |
|||
9000 |
XmlWriter() |
||
9001 |
: m_tagIsOpen( false ), |
||
9002 |
m_needsNewline( false ), |
||
9003 |
m_os( &Catch::cout() ) |
||
9004 |
{} |
||
9005 |
|||
9006 |
XmlWriter( std::ostream& os ) |
||
9007 |
: m_tagIsOpen( false ), |
||
9008 |
m_needsNewline( false ), |
||
9009 |
m_os( &os ) |
||
9010 |
{} |
||
9011 |
|||
9012 |
~XmlWriter() { |
||
9013 |
while( !m_tags.empty() ) |
||
9014 |
endElement(); |
||
9015 |
} |
||
9016 |
|||
9017 |
XmlWriter& startElement( std::string const& name ) { |
||
9018 |
ensureTagClosed(); |
||
9019 |
newlineIfNecessary(); |
||
9020 |
stream() << m_indent << "<" << name; |
||
9021 |
m_tags.push_back( name ); |
||
9022 |
m_indent += " "; |
||
9023 |
m_tagIsOpen = true; |
||
9024 |
return *this; |
||
9025 |
} |
||
9026 |
|||
9027 |
ScopedElement scopedElement( std::string const& name ) { |
||
9028 |
ScopedElement scoped( this ); |
||
9029 |
startElement( name ); |
||
9030 |
return scoped; |
||
9031 |
} |
||
9032 |
|||
9033 |
XmlWriter& endElement() { |
||
9034 |
newlineIfNecessary(); |
||
9035 |
m_indent = m_indent.substr( 0, m_indent.size()-2 ); |
||
9036 |
if( m_tagIsOpen ) { |
||
9037 |
stream() << "/>\n"; |
||
9038 |
m_tagIsOpen = false; |
||
9039 |
} |
||
9040 |
else { |
||
9041 |
stream() << m_indent << "</" << m_tags.back() << ">\n"; |
||
9042 |
} |
||
9043 |
m_tags.pop_back(); |
||
9044 |
return *this; |
||
9045 |
} |
||
9046 |
|||
9047 |
XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { |
||
9048 |
if( !name.empty() && !attribute.empty() ) |
||
9049 |
stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; |
||
9050 |
return *this; |
||
9051 |
} |
||
9052 |
|||
9053 |
XmlWriter& writeAttribute( std::string const& name, bool attribute ) { |
||
9054 |
stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; |
||
9055 |
return *this; |
||
9056 |
} |
||
9057 |
|||
9058 |
template<typename T> |
||
9059 |
XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { |
||
9060 |
std::ostringstream oss; |
||
9061 |
oss << attribute; |
||
9062 |
return writeAttribute( name, oss.str() ); |
||
9063 |
} |
||
9064 |
|||
9065 |
XmlWriter& writeText( std::string const& text, bool indent = true ) { |
||
9066 |
if( !text.empty() ){ |
||
9067 |
bool tagWasOpen = m_tagIsOpen; |
||
9068 |
ensureTagClosed(); |
||
9069 |
if( tagWasOpen && indent ) |
||
9070 |
stream() << m_indent; |
||
9071 |
stream() << XmlEncode( text ); |
||
9072 |
m_needsNewline = true; |
||
9073 |
} |
||
9074 |
return *this; |
||
9075 |
} |
||
9076 |
|||
9077 |
XmlWriter& writeComment( std::string const& text ) { |
||
9078 |
ensureTagClosed(); |
||
9079 |
stream() << m_indent << "<!--" << text << "-->"; |
||
9080 |
m_needsNewline = true; |
||
9081 |
return *this; |
||
9082 |
} |
||
9083 |
|||
9084 |
XmlWriter& writeBlankLine() { |
||
9085 |
ensureTagClosed(); |
||
9086 |
stream() << "\n"; |
||
9087 |
return *this; |
||
9088 |
} |
||
9089 |
|||
9090 |
void setStream( std::ostream& os ) { |
||
9091 |
m_os = &os; |
||
9092 |
} |
||
9093 |
|||
9094 |
private: |
||
9095 |
XmlWriter( XmlWriter const& ); |
||
9096 |
void operator=( XmlWriter const& ); |
||
9097 |
|||
9098 |
std::ostream& stream() { |
||
9099 |
return *m_os; |
||
9100 |
} |
||
9101 |
|||
9102 |
void ensureTagClosed() { |
||
9103 |
if( m_tagIsOpen ) { |
||
9104 |
stream() << ">\n"; |
||
9105 |
m_tagIsOpen = false; |
||
9106 |
} |
||
9107 |
} |
||
9108 |
|||
9109 |
void newlineIfNecessary() { |
||
9110 |
if( m_needsNewline ) { |
||
9111 |
stream() << "\n"; |
||
9112 |
m_needsNewline = false; |
||
9113 |
} |
||
9114 |
} |
||
9115 |
|||
9116 |
bool m_tagIsOpen; |
||
9117 |
bool m_needsNewline; |
||
9118 |
std::vector<std::string> m_tags; |
||
9119 |
std::string m_indent; |
||
9120 |
std::ostream* m_os; |
||
9121 |
}; |
||
9122 |
|||
9123 |
} |
||
9124 |
// #included from: catch_reenable_warnings.h |
||
9125 |
|||
9126 |
#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED |
||
9127 |
|||
9128 |
#ifdef __clang__ |
||
9129 |
# ifdef __ICC // icpc defines the __clang__ macro |
||
9130 |
# pragma warning(pop) |
||
9131 |
# else |
||
9132 |
# pragma clang diagnostic pop |
||
9133 |
# endif |
||
9134 |
#elif defined __GNUC__ |
||
9135 |
# pragma GCC diagnostic pop |
||
9136 |
#endif |
||
9137 |
|||
9138 |
|||
9139 |
namespace Catch { |
||
9140 |
class XmlReporter : public StreamingReporterBase { |
||
9141 |
public: |
||
9142 |
XmlReporter( ReporterConfig const& _config ) |
||
9143 |
: StreamingReporterBase( _config ), |
||
9144 |
m_sectionDepth( 0 ) |
||
9145 |
{ |
||
9146 |
m_reporterPrefs.shouldRedirectStdOut = true; |
||
9147 |
} |
||
9148 |
|||
9149 |
virtual ~XmlReporter() CATCH_OVERRIDE; |
||
9150 |
|||
9151 |
static std::string getDescription() { |
||
9152 |
return "Reports test results as an XML document"; |
||
9153 |
} |
||
9154 |
|||
9155 |
public: // StreamingReporterBase |
||
9156 |
|||
9157 |
virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { |
||
9158 |
StreamingReporterBase::noMatchingTestCases( s ); |
||
9159 |
} |
||
9160 |
|||
9161 |
virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { |
||
9162 |
StreamingReporterBase::testRunStarting( testInfo ); |
||
9163 |
m_xml.setStream( stream ); |
||
9164 |
m_xml.startElement( "Catch" ); |
||
9165 |
if( !m_config->name().empty() ) |
||
9166 |
m_xml.writeAttribute( "name", m_config->name() ); |
||
9167 |
} |
||
9168 |
|||
9169 |
virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { |
||
9170 |
StreamingReporterBase::testGroupStarting( groupInfo ); |
||
9171 |
m_xml.startElement( "Group" ) |
||
9172 |
.writeAttribute( "name", groupInfo.name ); |
||
9173 |
} |
||
9174 |
|||
9175 |
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { |
||
9176 |
StreamingReporterBase::testCaseStarting(testInfo); |
||
9177 |
m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); |
||
9178 |
|||
9179 |
if ( m_config->showDurations() == ShowDurations::Always ) |
||
9180 |
m_testCaseTimer.start(); |
||
9181 |
} |
||
9182 |
|||
9183 |
virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { |
||
9184 |
StreamingReporterBase::sectionStarting( sectionInfo ); |
||
9185 |
if( m_sectionDepth++ > 0 ) { |
||
9186 |
m_xml.startElement( "Section" ) |
||
9187 |
.writeAttribute( "name", trim( sectionInfo.name ) ) |
||
9188 |
.writeAttribute( "description", sectionInfo.description ); |
||
9189 |
} |
||
9190 |
} |
||
9191 |
|||
9192 |
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } |
||
9193 |
|||
9194 |
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { |
||
9195 |
const AssertionResult& assertionResult = assertionStats.assertionResult; |
||
9196 |
|||
9197 |
// Print any info messages in <Info> tags. |
||
9198 |
if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { |
||
9199 |
for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); |
||
9200 |
it != itEnd; |
||
9201 |
++it ) { |
||
9202 |
if( it->type == ResultWas::Info ) { |
||
9203 |
m_xml.scopedElement( "Info" ) |
||
9204 |
.writeText( it->message ); |
||
9205 |
} else if ( it->type == ResultWas::Warning ) { |
||
9206 |
m_xml.scopedElement( "Warning" ) |
||
9207 |
.writeText( it->message ); |
||
9208 |
} |
||
9209 |
} |
||
9210 |
} |
||
9211 |
|||
9212 |
// Drop out if result was successful but we're not printing them. |
||
9213 |
if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) |
||
9214 |
return true; |
||
9215 |
|||
9216 |
// Print the expression if there is one. |
||
9217 |
if( assertionResult.hasExpression() ) { |
||
9218 |
m_xml.startElement( "Expression" ) |
||
9219 |
.writeAttribute( "success", assertionResult.succeeded() ) |
||
9220 |
.writeAttribute( "type", assertionResult.getTestMacroName() ) |
||
9221 |
.writeAttribute( "filename", assertionResult.getSourceInfo().file ) |
||
9222 |
.writeAttribute( "line", assertionResult.getSourceInfo().line ); |
||
9223 |
|||
9224 |
m_xml.scopedElement( "Original" ) |
||
9225 |
.writeText( assertionResult.getExpression() ); |
||
9226 |
m_xml.scopedElement( "Expanded" ) |
||
9227 |
.writeText( assertionResult.getExpandedExpression() ); |
||
9228 |
} |
||
9229 |
|||
9230 |
// And... Print a result applicable to each result type. |
||
9231 |
switch( assertionResult.getResultType() ) { |
||
9232 |
case ResultWas::ThrewException: |
||
9233 |
m_xml.scopedElement( "Exception" ) |
||
9234 |
.writeAttribute( "filename", assertionResult.getSourceInfo().file ) |
||
9235 |
.writeAttribute( "line", assertionResult.getSourceInfo().line ) |
||
9236 |
.writeText( assertionResult.getMessage() ); |
||
9237 |
break; |
||
9238 |
case ResultWas::FatalErrorCondition: |
||
9239 |
m_xml.scopedElement( "Fatal Error Condition" ) |
||
9240 |
.writeAttribute( "filename", assertionResult.getSourceInfo().file ) |
||
9241 |
.writeAttribute( "line", assertionResult.getSourceInfo().line ) |
||
9242 |
.writeText( assertionResult.getMessage() ); |
||
9243 |
break; |
||
9244 |
case ResultWas::Info: |
||
9245 |
m_xml.scopedElement( "Info" ) |
||
9246 |
.writeText( assertionResult.getMessage() ); |
||
9247 |
break; |
||
9248 |
case ResultWas::Warning: |
||
9249 |
// Warning will already have been written |
||
9250 |
break; |
||
9251 |
case ResultWas::ExplicitFailure: |
||
9252 |
m_xml.scopedElement( "Failure" ) |
||
9253 |
.writeText( assertionResult.getMessage() ); |
||
9254 |
break; |
||
9255 |
default: |
||
9256 |
break; |
||
9257 |
} |
||
9258 |
|||
9259 |
if( assertionResult.hasExpression() ) |
||
9260 |
m_xml.endElement(); |
||
9261 |
|||
9262 |
return true; |
||
9263 |
} |
||
9264 |
|||
9265 |
virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { |
||
9266 |
StreamingReporterBase::sectionEnded( sectionStats ); |
||
9267 |
if( --m_sectionDepth > 0 ) { |
||
9268 |
XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); |
||
9269 |
e.writeAttribute( "successes", sectionStats.assertions.passed ); |
||
9270 |
e.writeAttribute( "failures", sectionStats.assertions.failed ); |
||
9271 |
e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); |
||
9272 |
|||
9273 |
if ( m_config->showDurations() == ShowDurations::Always ) |
||
9274 |
e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); |
||
9275 |
|||
9276 |
m_xml.endElement(); |
||
9277 |
} |
||
9278 |
} |
||
9279 |
|||
9280 |
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { |
||
9281 |
StreamingReporterBase::testCaseEnded( testCaseStats ); |
||
9282 |
XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); |
||
9283 |
e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); |
||
9284 |
|||
9285 |
if ( m_config->showDurations() == ShowDurations::Always ) |
||
9286 |
e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); |
||
9287 |
|||
9288 |
m_xml.endElement(); |
||
9289 |
} |
||
9290 |
|||
9291 |
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { |
||
9292 |
StreamingReporterBase::testGroupEnded( testGroupStats ); |
||
9293 |
// TODO: Check testGroupStats.aborting and act accordingly. |
||
9294 |
m_xml.scopedElement( "OverallResults" ) |
||
9295 |
.writeAttribute( "successes", testGroupStats.totals.assertions.passed ) |
||
9296 |
.writeAttribute( "failures", testGroupStats.totals.assertions.failed ) |
||
9297 |
.writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); |
||
9298 |
m_xml.endElement(); |
||
9299 |
} |
||
9300 |
|||
9301 |
virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { |
||
9302 |
StreamingReporterBase::testRunEnded( testRunStats ); |
||
9303 |
m_xml.scopedElement( "OverallResults" ) |
||
9304 |
.writeAttribute( "successes", testRunStats.totals.assertions.passed ) |
||
9305 |
.writeAttribute( "failures", testRunStats.totals.assertions.failed ) |
||
9306 |
.writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); |
||
9307 |
m_xml.endElement(); |
||
9308 |
} |
||
9309 |
|||
9310 |
private: |
||
9311 |
Timer m_testCaseTimer; |
||
9312 |
XmlWriter m_xml; |
||
9313 |
int m_sectionDepth; |
||
9314 |
}; |
||
9315 |
|||
9316 |
✓✗ | 4 |
INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) |
9317 |
|||
9318 |
} // end namespace Catch |
||
9319 |
|||
9320 |
// #included from: ../reporters/catch_reporter_junit.hpp |
||
9321 |
#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED |
||
9322 |
|||
9323 |
#include <assert.h> |
||
9324 |
|||
9325 |
namespace Catch { |
||
9326 |
|||
9327 |
class JunitReporter : public CumulativeReporterBase { |
||
9328 |
public: |
||
9329 |
JunitReporter( ReporterConfig const& _config ) |
||
9330 |
: CumulativeReporterBase( _config ), |
||
9331 |
xml( _config.stream() ) |
||
9332 |
{ |
||
9333 |
m_reporterPrefs.shouldRedirectStdOut = true; |
||
9334 |
} |
||
9335 |
|||
9336 |
virtual ~JunitReporter() CATCH_OVERRIDE; |
||
9337 |
|||
9338 |
static std::string getDescription() { |
||
9339 |
return "Reports test results in an XML format that looks like Ant's junitreport target"; |
||
9340 |
} |
||
9341 |
|||
9342 |
virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} |
||
9343 |
|||
9344 |
virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { |
||
9345 |
CumulativeReporterBase::testRunStarting( runInfo ); |
||
9346 |
xml.startElement( "testsuites" ); |
||
9347 |
} |
||
9348 |
|||
9349 |
virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { |
||
9350 |
suiteTimer.start(); |
||
9351 |
stdOutForSuite.str(""); |
||
9352 |
stdErrForSuite.str(""); |
||
9353 |
unexpectedExceptions = 0; |
||
9354 |
CumulativeReporterBase::testGroupStarting( groupInfo ); |
||
9355 |
} |
||
9356 |
|||
9357 |
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { |
||
9358 |
if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) |
||
9359 |
unexpectedExceptions++; |
||
9360 |
return CumulativeReporterBase::assertionEnded( assertionStats ); |
||
9361 |
} |
||
9362 |
|||
9363 |
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { |
||
9364 |
stdOutForSuite << testCaseStats.stdOut; |
||
9365 |
stdErrForSuite << testCaseStats.stdErr; |
||
9366 |
CumulativeReporterBase::testCaseEnded( testCaseStats ); |
||
9367 |
} |
||
9368 |
|||
9369 |
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { |
||
9370 |
double suiteTime = suiteTimer.getElapsedSeconds(); |
||
9371 |
CumulativeReporterBase::testGroupEnded( testGroupStats ); |
||
9372 |
writeGroup( *m_testGroups.back(), suiteTime ); |
||
9373 |
} |
||
9374 |
|||
9375 |
virtual void testRunEndedCumulative() CATCH_OVERRIDE { |
||
9376 |
xml.endElement(); |
||
9377 |
} |
||
9378 |
|||
9379 |
void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { |
||
9380 |
XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); |
||
9381 |
TestGroupStats const& stats = groupNode.value; |
||
9382 |
xml.writeAttribute( "name", stats.groupInfo.name ); |
||
9383 |
xml.writeAttribute( "errors", unexpectedExceptions ); |
||
9384 |
xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); |
||
9385 |
xml.writeAttribute( "tests", stats.totals.assertions.total() ); |
||
9386 |
xml.writeAttribute( "hostname", "tbd" ); // !TBD |
||
9387 |
if( m_config->showDurations() == ShowDurations::Never ) |
||
9388 |
xml.writeAttribute( "time", "" ); |
||
9389 |
else |
||
9390 |
xml.writeAttribute( "time", suiteTime ); |
||
9391 |
xml.writeAttribute( "timestamp", "tbd" ); // !TBD |
||
9392 |
|||
9393 |
// Write test cases |
||
9394 |
for( TestGroupNode::ChildNodes::const_iterator |
||
9395 |
it = groupNode.children.begin(), itEnd = groupNode.children.end(); |
||
9396 |
it != itEnd; |
||
9397 |
++it ) |
||
9398 |
writeTestCase( **it ); |
||
9399 |
|||
9400 |
xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); |
||
9401 |
xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); |
||
9402 |
} |
||
9403 |
|||
9404 |
void writeTestCase( TestCaseNode const& testCaseNode ) { |
||
9405 |
TestCaseStats const& stats = testCaseNode.value; |
||
9406 |
|||
9407 |
// All test cases have exactly one section - which represents the |
||
9408 |
// test case itself. That section may have 0-n nested sections |
||
9409 |
assert( testCaseNode.children.size() == 1 ); |
||
9410 |
SectionNode const& rootSection = *testCaseNode.children.front(); |
||
9411 |
|||
9412 |
std::string className = stats.testInfo.className; |
||
9413 |
|||
9414 |
if( className.empty() ) { |
||
9415 |
if( rootSection.childSections.empty() ) |
||
9416 |
className = "global"; |
||
9417 |
} |
||
9418 |
writeSection( className, "", rootSection ); |
||
9419 |
} |
||
9420 |
|||
9421 |
void writeSection( std::string const& className, |
||
9422 |
std::string const& rootName, |
||
9423 |
SectionNode const& sectionNode ) { |
||
9424 |
std::string name = trim( sectionNode.stats.sectionInfo.name ); |
||
9425 |
if( !rootName.empty() ) |
||
9426 |
name = rootName + "/" + name; |
||
9427 |
|||
9428 |
if( !sectionNode.assertions.empty() || |
||
9429 |
!sectionNode.stdOut.empty() || |
||
9430 |
!sectionNode.stdErr.empty() ) { |
||
9431 |
XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); |
||
9432 |
if( className.empty() ) { |
||
9433 |
xml.writeAttribute( "classname", name ); |
||
9434 |
xml.writeAttribute( "name", "root" ); |
||
9435 |
} |
||
9436 |
else { |
||
9437 |
xml.writeAttribute( "classname", className ); |
||
9438 |
xml.writeAttribute( "name", name ); |
||
9439 |
} |
||
9440 |
xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); |
||
9441 |
|||
9442 |
writeAssertions( sectionNode ); |
||
9443 |
|||
9444 |
if( !sectionNode.stdOut.empty() ) |
||
9445 |
xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); |
||
9446 |
if( !sectionNode.stdErr.empty() ) |
||
9447 |
xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); |
||
9448 |
} |
||
9449 |
for( SectionNode::ChildSections::const_iterator |
||
9450 |
it = sectionNode.childSections.begin(), |
||
9451 |
itEnd = sectionNode.childSections.end(); |
||
9452 |
it != itEnd; |
||
9453 |
++it ) |
||
9454 |
if( className.empty() ) |
||
9455 |
writeSection( name, "", **it ); |
||
9456 |
else |
||
9457 |
writeSection( className, name, **it ); |
||
9458 |
} |
||
9459 |
|||
9460 |
void writeAssertions( SectionNode const& sectionNode ) { |
||
9461 |
for( SectionNode::Assertions::const_iterator |
||
9462 |
it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); |
||
9463 |
it != itEnd; |
||
9464 |
++it ) |
||
9465 |
writeAssertion( *it ); |
||
9466 |
} |
||
9467 |
void writeAssertion( AssertionStats const& stats ) { |
||
9468 |
AssertionResult const& result = stats.assertionResult; |
||
9469 |
if( !result.isOk() ) { |
||
9470 |
std::string elementName; |
||
9471 |
switch( result.getResultType() ) { |
||
9472 |
case ResultWas::ThrewException: |
||
9473 |
case ResultWas::FatalErrorCondition: |
||
9474 |
elementName = "error"; |
||
9475 |
break; |
||
9476 |
case ResultWas::ExplicitFailure: |
||
9477 |
elementName = "failure"; |
||
9478 |
break; |
||
9479 |
case ResultWas::ExpressionFailed: |
||
9480 |
elementName = "failure"; |
||
9481 |
break; |
||
9482 |
case ResultWas::DidntThrowException: |
||
9483 |
elementName = "failure"; |
||
9484 |
break; |
||
9485 |
|||
9486 |
// We should never see these here: |
||
9487 |
case ResultWas::Info: |
||
9488 |
case ResultWas::Warning: |
||
9489 |
case ResultWas::Ok: |
||
9490 |
case ResultWas::Unknown: |
||
9491 |
case ResultWas::FailureBit: |
||
9492 |
case ResultWas::Exception: |
||
9493 |
elementName = "internalError"; |
||
9494 |
break; |
||
9495 |
} |
||
9496 |
|||
9497 |
XmlWriter::ScopedElement e = xml.scopedElement( elementName ); |
||
9498 |
|||
9499 |
xml.writeAttribute( "message", result.getExpandedExpression() ); |
||
9500 |
xml.writeAttribute( "type", result.getTestMacroName() ); |
||
9501 |
|||
9502 |
std::ostringstream oss; |
||
9503 |
if( !result.getMessage().empty() ) |
||
9504 |
oss << result.getMessage() << "\n"; |
||
9505 |
for( std::vector<MessageInfo>::const_iterator |
||
9506 |
it = stats.infoMessages.begin(), |
||
9507 |
itEnd = stats.infoMessages.end(); |
||
9508 |
it != itEnd; |
||
9509 |
++it ) |
||
9510 |
if( it->type == ResultWas::Info ) |
||
9511 |
oss << it->message << "\n"; |
||
9512 |
|||
9513 |
oss << "at " << result.getSourceInfo(); |
||
9514 |
xml.writeText( oss.str(), false ); |
||
9515 |
} |
||
9516 |
} |
||
9517 |
|||
9518 |
XmlWriter xml; |
||
9519 |
Timer suiteTimer; |
||
9520 |
std::ostringstream stdOutForSuite; |
||
9521 |
std::ostringstream stdErrForSuite; |
||
9522 |
unsigned int unexpectedExceptions; |
||
9523 |
}; |
||
9524 |
|||
9525 |
✓✗ | 4 |
INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) |
9526 |
|||
9527 |
} // end namespace Catch |
||
9528 |
|||
9529 |
// #included from: ../reporters/catch_reporter_console.hpp |
||
9530 |
#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED |
||
9531 |
|||
9532 |
namespace Catch { |
||
9533 |
|||
9534 |
struct ConsoleReporter : StreamingReporterBase { |
||
9535 |
ConsoleReporter( ReporterConfig const& _config ) |
||
9536 |
1 |
: StreamingReporterBase( _config ), |
|
9537 |
2 |
m_headerPrinted( false ) |
|
9538 |
{} |
||
9539 |
|||
9540 |
virtual ~ConsoleReporter() CATCH_OVERRIDE; |
||
9541 |
static std::string getDescription() { |
||
9542 |
return "Reports test results as plain lines of text"; |
||
9543 |
} |
||
9544 |
|||
9545 |
virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { |
||
9546 |
stream << "No test cases matched '" << spec << "'" << std::endl; |
||
9547 |
} |
||
9548 |
|||
9549 |
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { |
||
9550 |
} |
||
9551 |
|||
9552 |
1432923 |
virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { |
|
9553 |
1432923 |
AssertionResult const& result = _assertionStats.assertionResult; |
|
9554 |
|||
9555 |
1432923 |
bool printInfoMessages = true; |
|
9556 |
|||
9557 |
// Drop out if result was successful and we're not printing those |
||
9558 |
✓✗✗✓ ✓✗ |
4298769 |
if( !m_config->includeSuccessfulResults() && result.isOk() ) { |
9559 |
✗✓ | 1432923 |
if( result.getResultType() != ResultWas::Warning ) |
9560 |
return false; |
||
9561 |
printInfoMessages = false; |
||
9562 |
} |
||
9563 |
|||
9564 |
lazyPrint(); |
||
9565 |
|||
9566 |
AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); |
||
9567 |
printer.print(); |
||
9568 |
stream << std::endl; |
||
9569 |
return true; |
||
9570 |
} |
||
9571 |
|||
9572 |
1145 |
virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { |
|
9573 |
1145 |
m_headerPrinted = false; |
|
9574 |
2290 |
StreamingReporterBase::sectionStarting( _sectionInfo ); |
|
9575 |
1145 |
} |
|
9576 |
1145 |
virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { |
|
9577 |
✗✓ | 1145 |
if( _sectionStats.missingAssertions ) { |
9578 |
lazyPrint(); |
||
9579 |
Colour colour( Colour::ResultError ); |
||
9580 |
if( m_sectionStack.size() > 1 ) |
||
9581 |
stream << "\nNo assertions in section"; |
||
9582 |
else |
||
9583 |
stream << "\nNo assertions in test case"; |
||
9584 |
stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; |
||
9585 |
} |
||
9586 |
✗✓ | 1145 |
if( m_headerPrinted ) { |
9587 |
if( m_config->showDurations() == ShowDurations::Always ) |
||
9588 |
stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; |
||
9589 |
m_headerPrinted = false; |
||
9590 |
} |
||
9591 |
else { |
||
9592 |
✗✓ | 2290 |
if( m_config->showDurations() == ShowDurations::Always ) |
9593 |
stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; |
||
9594 |
} |
||
9595 |
2290 |
StreamingReporterBase::sectionEnded( _sectionStats ); |
|
9596 |
1145 |
} |
|
9597 |
|||
9598 |
394 |
virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { |
|
9599 |
788 |
StreamingReporterBase::testCaseEnded( _testCaseStats ); |
|
9600 |
394 |
m_headerPrinted = false; |
|
9601 |
394 |
} |
|
9602 |
1 |
virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { |
|
9603 |
✗✓ | 1 |
if( currentGroupInfo.used ) { |
9604 |
printSummaryDivider(); |
||
9605 |
stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; |
||
9606 |
printTotals( _testGroupStats.totals ); |
||
9607 |
stream << "\n" << std::endl; |
||
9608 |
} |
||
9609 |
2 |
StreamingReporterBase::testGroupEnded( _testGroupStats ); |
|
9610 |
1 |
} |
|
9611 |
1 |
virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { |
|
9612 |
1 |
printTotalsDivider( _testRunStats.totals ); |
|
9613 |
1 |
printTotals( _testRunStats.totals ); |
|
9614 |
2 |
stream << std::endl; |
|
9615 |
1 |
StreamingReporterBase::testRunEnded( _testRunStats ); |
|
9616 |
1 |
} |
|
9617 |
|||
9618 |
private: |
||
9619 |
|||
9620 |
class AssertionPrinter { |
||
9621 |
void operator= ( AssertionPrinter const& ); |
||
9622 |
public: |
||
9623 |
AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) |
||
9624 |
: stream( _stream ), |
||
9625 |
stats( _stats ), |
||
9626 |
result( _stats.assertionResult ), |
||
9627 |
colour( Colour::None ), |
||
9628 |
message( result.getMessage() ), |
||
9629 |
messages( _stats.infoMessages ), |
||
9630 |
printInfoMessages( _printInfoMessages ) |
||
9631 |
{ |
||
9632 |
switch( result.getResultType() ) { |
||
9633 |
case ResultWas::Ok: |
||
9634 |
colour = Colour::Success; |
||
9635 |
passOrFail = "PASSED"; |
||
9636 |
//if( result.hasMessage() ) |
||
9637 |
if( _stats.infoMessages.size() == 1 ) |
||
9638 |
messageLabel = "with message"; |
||
9639 |
if( _stats.infoMessages.size() > 1 ) |
||
9640 |
messageLabel = "with messages"; |
||
9641 |
break; |
||
9642 |
case ResultWas::ExpressionFailed: |
||
9643 |
if( result.isOk() ) { |
||
9644 |
colour = Colour::Success; |
||
9645 |
passOrFail = "FAILED - but was ok"; |
||
9646 |
} |
||
9647 |
else { |
||
9648 |
colour = Colour::Error; |
||
9649 |
passOrFail = "FAILED"; |
||
9650 |
} |
||
9651 |
if( _stats.infoMessages.size() == 1 ) |
||
9652 |
messageLabel = "with message"; |
||
9653 |
if( _stats.infoMessages.size() > 1 ) |
||
9654 |
messageLabel = "with messages"; |
||
9655 |
break; |
||
9656 |
case ResultWas::ThrewException: |
||
9657 |
colour = Colour::Error; |
||
9658 |
passOrFail = "FAILED"; |
||
9659 |
messageLabel = "due to unexpected exception with message"; |
||
9660 |
break; |
||
9661 |
case ResultWas::FatalErrorCondition: |
||
9662 |
colour = Colour::Error; |
||
9663 |
passOrFail = "FAILED"; |
||
9664 |
messageLabel = "due to a fatal error condition"; |
||
9665 |
break; |
||
9666 |
case ResultWas::DidntThrowException: |
||
9667 |
colour = Colour::Error; |
||
9668 |
passOrFail = "FAILED"; |
||
9669 |
messageLabel = "because no exception was thrown where one was expected"; |
||
9670 |
break; |
||
9671 |
case ResultWas::Info: |
||
9672 |
messageLabel = "info"; |
||
9673 |
break; |
||
9674 |
case ResultWas::Warning: |
||
9675 |
messageLabel = "warning"; |
||
9676 |
break; |
||
9677 |
case ResultWas::ExplicitFailure: |
||
9678 |
passOrFail = "FAILED"; |
||
9679 |
colour = Colour::Error; |
||
9680 |
if( _stats.infoMessages.size() == 1 ) |
||
9681 |
messageLabel = "explicitly with message"; |
||
9682 |
if( _stats.infoMessages.size() > 1 ) |
||
9683 |
messageLabel = "explicitly with messages"; |
||
9684 |
break; |
||
9685 |
// These cases are here to prevent compiler warnings |
||
9686 |
case ResultWas::Unknown: |
||
9687 |
case ResultWas::FailureBit: |
||
9688 |
case ResultWas::Exception: |
||
9689 |
passOrFail = "** internal error **"; |
||
9690 |
colour = Colour::Error; |
||
9691 |
break; |
||
9692 |
} |
||
9693 |
} |
||
9694 |
|||
9695 |
void print() const { |
||
9696 |
printSourceInfo(); |
||
9697 |
if( stats.totals.assertions.total() > 0 ) { |
||
9698 |
if( result.isOk() ) |
||
9699 |
stream << "\n"; |
||
9700 |
printResultType(); |
||
9701 |
printOriginalExpression(); |
||
9702 |
printReconstructedExpression(); |
||
9703 |
} |
||
9704 |
else { |
||
9705 |
stream << "\n"; |
||
9706 |
} |
||
9707 |
printMessage(); |
||
9708 |
} |
||
9709 |
|||
9710 |
private: |
||
9711 |
void printResultType() const { |
||
9712 |
if( !passOrFail.empty() ) { |
||
9713 |
Colour colourGuard( colour ); |
||
9714 |
stream << passOrFail << ":\n"; |
||
9715 |
} |
||
9716 |
} |
||
9717 |
void printOriginalExpression() const { |
||
9718 |
if( result.hasExpression() ) { |
||
9719 |
Colour colourGuard( Colour::OriginalExpression ); |
||
9720 |
stream << " "; |
||
9721 |
stream << result.getExpressionInMacro(); |
||
9722 |
stream << "\n"; |
||
9723 |
} |
||
9724 |
} |
||
9725 |
void printReconstructedExpression() const { |
||
9726 |
if( result.hasExpandedExpression() ) { |
||
9727 |
stream << "with expansion:\n"; |
||
9728 |
Colour colourGuard( Colour::ReconstructedExpression ); |
||
9729 |
stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; |
||
9730 |
} |
||
9731 |
} |
||
9732 |
void printMessage() const { |
||
9733 |
if( !messageLabel.empty() ) |
||
9734 |
stream << messageLabel << ":" << "\n"; |
||
9735 |
for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end(); |
||
9736 |
it != itEnd; |
||
9737 |
++it ) { |
||
9738 |
// If this assertion is a warning ignore any INFO messages |
||
9739 |
if( printInfoMessages || it->type != ResultWas::Info ) |
||
9740 |
stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; |
||
9741 |
} |
||
9742 |
} |
||
9743 |
void printSourceInfo() const { |
||
9744 |
Colour colourGuard( Colour::FileName ); |
||
9745 |
stream << result.getSourceInfo() << ": "; |
||
9746 |
} |
||
9747 |
|||
9748 |
std::ostream& stream; |
||
9749 |
AssertionStats const& stats; |
||
9750 |
AssertionResult const& result; |
||
9751 |
Colour::Code colour; |
||
9752 |
std::string passOrFail; |
||
9753 |
std::string messageLabel; |
||
9754 |
std::string message; |
||
9755 |
std::vector<MessageInfo> messages; |
||
9756 |
bool printInfoMessages; |
||
9757 |
}; |
||
9758 |
|||
9759 |
void lazyPrint() { |
||
9760 |
|||
9761 |
if( !currentTestRunInfo.used ) |
||
9762 |
lazyPrintRunInfo(); |
||
9763 |
if( !currentGroupInfo.used ) |
||
9764 |
lazyPrintGroupInfo(); |
||
9765 |
|||
9766 |
if( !m_headerPrinted ) { |
||
9767 |
printTestCaseAndSectionHeader(); |
||
9768 |
m_headerPrinted = true; |
||
9769 |
} |
||
9770 |
} |
||
9771 |
void lazyPrintRunInfo() { |
||
9772 |
stream << "\n" << getLineOfChars<'~'>() << "\n"; |
||
9773 |
Colour colour( Colour::SecondaryText ); |
||
9774 |
stream << currentTestRunInfo->name |
||
9775 |
<< " is a Catch v" << libraryVersion << " host application.\n" |
||
9776 |
<< "Run with -? for options\n\n"; |
||
9777 |
|||
9778 |
if( m_config->rngSeed() != 0 ) |
||
9779 |
stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; |
||
9780 |
|||
9781 |
currentTestRunInfo.used = true; |
||
9782 |
} |
||
9783 |
void lazyPrintGroupInfo() { |
||
9784 |
if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { |
||
9785 |
printClosedHeader( "Group: " + currentGroupInfo->name ); |
||
9786 |
currentGroupInfo.used = true; |
||
9787 |
} |
||
9788 |
} |
||
9789 |
void printTestCaseAndSectionHeader() { |
||
9790 |
assert( !m_sectionStack.empty() ); |
||
9791 |
printOpenHeader( currentTestCaseInfo->name ); |
||
9792 |
|||
9793 |
if( m_sectionStack.size() > 1 ) { |
||
9794 |
Colour colourGuard( Colour::Headers ); |
||
9795 |
|||
9796 |
std::vector<SectionInfo>::const_iterator |
||
9797 |
it = m_sectionStack.begin()+1, // Skip first section (test case) |
||
9798 |
itEnd = m_sectionStack.end(); |
||
9799 |
for( ; it != itEnd; ++it ) |
||
9800 |
printHeaderString( it->name, 2 ); |
||
9801 |
} |
||
9802 |
|||
9803 |
SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; |
||
9804 |
|||
9805 |
if( !lineInfo.empty() ){ |
||
9806 |
stream << getLineOfChars<'-'>() << "\n"; |
||
9807 |
Colour colourGuard( Colour::FileName ); |
||
9808 |
stream << lineInfo << "\n"; |
||
9809 |
} |
||
9810 |
stream << getLineOfChars<'.'>() << "\n" << std::endl; |
||
9811 |
} |
||
9812 |
|||
9813 |
void printClosedHeader( std::string const& _name ) { |
||
9814 |
printOpenHeader( _name ); |
||
9815 |
stream << getLineOfChars<'.'>() << "\n"; |
||
9816 |
} |
||
9817 |
void printOpenHeader( std::string const& _name ) { |
||
9818 |
stream << getLineOfChars<'-'>() << "\n"; |
||
9819 |
{ |
||
9820 |
Colour colourGuard( Colour::Headers ); |
||
9821 |
printHeaderString( _name ); |
||
9822 |
} |
||
9823 |
} |
||
9824 |
|||
9825 |
// if string has a : in first line will set indent to follow it on |
||
9826 |
// subsequent lines |
||
9827 |
void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { |
||
9828 |
std::size_t i = _string.find( ": " ); |
||
9829 |
if( i != std::string::npos ) |
||
9830 |
i+=2; |
||
9831 |
else |
||
9832 |
i = 0; |
||
9833 |
stream << Text( _string, TextAttributes() |
||
9834 |
.setIndent( indent+i) |
||
9835 |
.setInitialIndent( indent ) ) << "\n"; |
||
9836 |
} |
||
9837 |
|||
9838 |
struct SummaryColumn { |
||
9839 |
|||
9840 |
SummaryColumn( std::string const& _label, Colour::Code _colour ) |
||
9841 |
: label( _label ), |
||
9842 |
colour( _colour ) |
||
9843 |
{} |
||
9844 |
SummaryColumn addRow( std::size_t count ) { |
||
9845 |
std::ostringstream oss; |
||
9846 |
oss << count; |
||
9847 |
std::string row = oss.str(); |
||
9848 |
for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) { |
||
9849 |
while( it->size() < row.size() ) |
||
9850 |
*it = " " + *it; |
||
9851 |
while( it->size() > row.size() ) |
||
9852 |
row = " " + row; |
||
9853 |
} |
||
9854 |
rows.push_back( row ); |
||
9855 |
return *this; |
||
9856 |
} |
||
9857 |
|||
9858 |
std::string label; |
||
9859 |
Colour::Code colour; |
||
9860 |
std::vector<std::string> rows; |
||
9861 |
|||
9862 |
}; |
||
9863 |
|||
9864 |
1 |
void printTotals( Totals const& totals ) { |
|
9865 |
✗✓ | 2 |
if( totals.testCases.total() == 0 ) { |
9866 |
stream << Colour( Colour::Warning ) << "No tests ran\n"; |
||
9867 |
} |
||
9868 |
✓✗✗✓ ✓✗ |
3 |
else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { |
9869 |
✓✗ | 2 |
stream << Colour( Colour::ResultSuccess ) << "All tests passed"; |
9870 |
2 |
stream << " (" |
|
9871 |
✓✗✓✗ |
8 |
<< pluralise( totals.assertions.passed, "assertion" ) << " in " |
9872 |
✓✗ | 7 |
<< pluralise( totals.testCases.passed, "test case" ) << ")" |
9873 |
✓✗ | 1 |
<< "\n"; |
9874 |
} |
||
9875 |
else { |
||
9876 |
|||
9877 |
std::vector<SummaryColumn> columns; |
||
9878 |
columns.push_back( SummaryColumn( "", Colour::None ) |
||
9879 |
.addRow( totals.testCases.total() ) |
||
9880 |
.addRow( totals.assertions.total() ) ); |
||
9881 |
columns.push_back( SummaryColumn( "passed", Colour::Success ) |
||
9882 |
.addRow( totals.testCases.passed ) |
||
9883 |
.addRow( totals.assertions.passed ) ); |
||
9884 |
columns.push_back( SummaryColumn( "failed", Colour::ResultError ) |
||
9885 |
.addRow( totals.testCases.failed ) |
||
9886 |
.addRow( totals.assertions.failed ) ); |
||
9887 |
columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) |
||
9888 |
.addRow( totals.testCases.failedButOk ) |
||
9889 |
.addRow( totals.assertions.failedButOk ) ); |
||
9890 |
|||
9891 |
printSummaryRow( "test cases", columns, 0 ); |
||
9892 |
printSummaryRow( "assertions", columns, 1 ); |
||
9893 |
} |
||
9894 |
1 |
} |
|
9895 |
void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) { |
||
9896 |
for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) { |
||
9897 |
std::string value = it->rows[row]; |
||
9898 |
if( it->label.empty() ) { |
||
9899 |
stream << label << ": "; |
||
9900 |
if( value != "0" ) |
||
9901 |
stream << value; |
||
9902 |
else |
||
9903 |
stream << Colour( Colour::Warning ) << "- none -"; |
||
9904 |
} |
||
9905 |
else if( value != "0" ) { |
||
9906 |
stream << Colour( Colour::LightGrey ) << " | "; |
||
9907 |
stream << Colour( it->colour ) |
||
9908 |
<< value << " " << it->label; |
||
9909 |
} |
||
9910 |
} |
||
9911 |
stream << "\n"; |
||
9912 |
} |
||
9913 |
|||
9914 |
static std::size_t makeRatio( std::size_t number, std::size_t total ) { |
||
9915 |
3 |
std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; |
|
9916 |
✗✓✗✓ ✗✓ |
3 |
return ( ratio == 0 && number > 0 ) ? 1 : ratio; |
9917 |
} |
||
9918 |
static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { |
||
9919 |
✗✗✗✗ ✗✓✗✗ |
1 |
if( i > j && i > k ) |
9920 |
return i; |
||
9921 |
✗✗✓✗ |
1 |
else if( j > k ) |
9922 |
return j; |
||
9923 |
else |
||
9924 |
return k; |
||
9925 |
} |
||
9926 |
|||
9927 |
1 |
void printTotalsDivider( Totals const& totals ) { |
|
9928 |
✓✗ | 2 |
if( totals.testCases.total() > 0 ) { |
9929 |
2 |
std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); |
|
9930 |
2 |
std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); |
|
9931 |
2 |
std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); |
|
9932 |
✓✗ | 1 |
while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) |
9933 |
findMax( failedRatio, failedButOkRatio, passedRatio )++; |
||
9934 |
✓✓ | 3 |
while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) |
9935 |
1 |
findMax( failedRatio, failedButOkRatio, passedRatio )--; |
|
9936 |
|||
9937 |
8 |
stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); |
|
9938 |
8 |
stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); |
|
9939 |
✓✗ | 2 |
if( totals.testCases.allPassed() ) |
9940 |
8 |
stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); |
|
9941 |
else |
||
9942 |
stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); |
||
9943 |
} |
||
9944 |
else { |
||
9945 |
stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); |
||
9946 |
} |
||
9947 |
1 |
stream << "\n"; |
|
9948 |
1 |
} |
|
9949 |
void printSummaryDivider() { |
||
9950 |
stream << getLineOfChars<'-'>() << "\n"; |
||
9951 |
} |
||
9952 |
|||
9953 |
private: |
||
9954 |
bool m_headerPrinted; |
||
9955 |
}; |
||
9956 |
|||
9957 |
✓✗ | 4 |
INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) |
9958 |
|||
9959 |
} // end namespace Catch |
||
9960 |
|||
9961 |
// #included from: ../reporters/catch_reporter_compact.hpp |
||
9962 |
#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED |
||
9963 |
|||
9964 |
namespace Catch { |
||
9965 |
|||
9966 |
struct CompactReporter : StreamingReporterBase { |
||
9967 |
|||
9968 |
CompactReporter( ReporterConfig const& _config ) |
||
9969 |
: StreamingReporterBase( _config ) |
||
9970 |
{} |
||
9971 |
|||
9972 |
virtual ~CompactReporter(); |
||
9973 |
|||
9974 |
static std::string getDescription() { |
||
9975 |
return "Reports test results on a single line, suitable for IDEs"; |
||
9976 |
} |
||
9977 |
|||
9978 |
virtual ReporterPreferences getPreferences() const { |
||
9979 |
ReporterPreferences prefs; |
||
9980 |
prefs.shouldRedirectStdOut = false; |
||
9981 |
return prefs; |
||
9982 |
} |
||
9983 |
|||
9984 |
virtual void noMatchingTestCases( std::string const& spec ) { |
||
9985 |
stream << "No test cases matched '" << spec << "'" << std::endl; |
||
9986 |
} |
||
9987 |
|||
9988 |
virtual void assertionStarting( AssertionInfo const& ) { |
||
9989 |
} |
||
9990 |
|||
9991 |
virtual bool assertionEnded( AssertionStats const& _assertionStats ) { |
||
9992 |
AssertionResult const& result = _assertionStats.assertionResult; |
||
9993 |
|||
9994 |
bool printInfoMessages = true; |
||
9995 |
|||
9996 |
// Drop out if result was successful and we're not printing those |
||
9997 |
if( !m_config->includeSuccessfulResults() && result.isOk() ) { |
||
9998 |
if( result.getResultType() != ResultWas::Warning ) |
||
9999 |
return false; |
||
10000 |
printInfoMessages = false; |
||
10001 |
} |
||
10002 |
|||
10003 |
AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); |
||
10004 |
printer.print(); |
||
10005 |
|||
10006 |
stream << std::endl; |
||
10007 |
return true; |
||
10008 |
} |
||
10009 |
|||
10010 |
virtual void testRunEnded( TestRunStats const& _testRunStats ) { |
||
10011 |
printTotals( _testRunStats.totals ); |
||
10012 |
stream << "\n" << std::endl; |
||
10013 |
StreamingReporterBase::testRunEnded( _testRunStats ); |
||
10014 |
} |
||
10015 |
|||
10016 |
private: |
||
10017 |
class AssertionPrinter { |
||
10018 |
void operator= ( AssertionPrinter const& ); |
||
10019 |
public: |
||
10020 |
AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) |
||
10021 |
: stream( _stream ) |
||
10022 |
, stats( _stats ) |
||
10023 |
, result( _stats.assertionResult ) |
||
10024 |
, messages( _stats.infoMessages ) |
||
10025 |
, itMessage( _stats.infoMessages.begin() ) |
||
10026 |
, printInfoMessages( _printInfoMessages ) |
||
10027 |
{} |
||
10028 |
|||
10029 |
void print() { |
||
10030 |
printSourceInfo(); |
||
10031 |
|||
10032 |
itMessage = messages.begin(); |
||
10033 |
|||
10034 |
switch( result.getResultType() ) { |
||
10035 |
case ResultWas::Ok: |
||
10036 |
printResultType( Colour::ResultSuccess, passedString() ); |
||
10037 |
printOriginalExpression(); |
||
10038 |
printReconstructedExpression(); |
||
10039 |
if ( ! result.hasExpression() ) |
||
10040 |
printRemainingMessages( Colour::None ); |
||
10041 |
else |
||
10042 |
printRemainingMessages(); |
||
10043 |
break; |
||
10044 |
case ResultWas::ExpressionFailed: |
||
10045 |
if( result.isOk() ) |
||
10046 |
printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); |
||
10047 |
else |
||
10048 |
printResultType( Colour::Error, failedString() ); |
||
10049 |
printOriginalExpression(); |
||
10050 |
printReconstructedExpression(); |
||
10051 |
printRemainingMessages(); |
||
10052 |
break; |
||
10053 |
case ResultWas::ThrewException: |
||
10054 |
printResultType( Colour::Error, failedString() ); |
||
10055 |
printIssue( "unexpected exception with message:" ); |
||
10056 |
printMessage(); |
||
10057 |
printExpressionWas(); |
||
10058 |
printRemainingMessages(); |
||
10059 |
break; |
||
10060 |
case ResultWas::FatalErrorCondition: |
||
10061 |
printResultType( Colour::Error, failedString() ); |
||
10062 |
printIssue( "fatal error condition with message:" ); |
||
10063 |
printMessage(); |
||
10064 |
printExpressionWas(); |
||
10065 |
printRemainingMessages(); |
||
10066 |
break; |
||
10067 |
case ResultWas::DidntThrowException: |
||
10068 |
printResultType( Colour::Error, failedString() ); |
||
10069 |
printIssue( "expected exception, got none" ); |
||
10070 |
printExpressionWas(); |
||
10071 |
printRemainingMessages(); |
||
10072 |
break; |
||
10073 |
case ResultWas::Info: |
||
10074 |
printResultType( Colour::None, "info" ); |
||
10075 |
printMessage(); |
||
10076 |
printRemainingMessages(); |
||
10077 |
break; |
||
10078 |
case ResultWas::Warning: |
||
10079 |
printResultType( Colour::None, "warning" ); |
||
10080 |
printMessage(); |
||
10081 |
printRemainingMessages(); |
||
10082 |
break; |
||
10083 |
case ResultWas::ExplicitFailure: |
||
10084 |
printResultType( Colour::Error, failedString() ); |
||
10085 |
printIssue( "explicitly" ); |
||
10086 |
printRemainingMessages( Colour::None ); |
||
10087 |
break; |
||
10088 |
// These cases are here to prevent compiler warnings |
||
10089 |
case ResultWas::Unknown: |
||
10090 |
case ResultWas::FailureBit: |
||
10091 |
case ResultWas::Exception: |
||
10092 |
printResultType( Colour::Error, "** internal error **" ); |
||
10093 |
break; |
||
10094 |
} |
||
10095 |
} |
||
10096 |
|||
10097 |
private: |
||
10098 |
// Colour::LightGrey |
||
10099 |
|||
10100 |
static Colour::Code dimColour() { return Colour::FileName; } |
||
10101 |
|||
10102 |
#ifdef CATCH_PLATFORM_MAC |
||
10103 |
static const char* failedString() { return "FAILED"; } |
||
10104 |
static const char* passedString() { return "PASSED"; } |
||
10105 |
#else |
||
10106 |
static const char* failedString() { return "failed"; } |
||
10107 |
static const char* passedString() { return "passed"; } |
||
10108 |
#endif |
||
10109 |
|||
10110 |
void printSourceInfo() const { |
||
10111 |
Colour colourGuard( Colour::FileName ); |
||
10112 |
stream << result.getSourceInfo() << ":"; |
||
10113 |
} |
||
10114 |
|||
10115 |
void printResultType( Colour::Code colour, std::string passOrFail ) const { |
||
10116 |
if( !passOrFail.empty() ) { |
||
10117 |
{ |
||
10118 |
Colour colourGuard( colour ); |
||
10119 |
stream << " " << passOrFail; |
||
10120 |
} |
||
10121 |
stream << ":"; |
||
10122 |
} |
||
10123 |
} |
||
10124 |
|||
10125 |
void printIssue( std::string issue ) const { |
||
10126 |
stream << " " << issue; |
||
10127 |
} |
||
10128 |
|||
10129 |
void printExpressionWas() { |
||
10130 |
if( result.hasExpression() ) { |
||
10131 |
stream << ";"; |
||
10132 |
{ |
||
10133 |
Colour colour( dimColour() ); |
||
10134 |
stream << " expression was:"; |
||
10135 |
} |
||
10136 |
printOriginalExpression(); |
||
10137 |
} |
||
10138 |
} |
||
10139 |
|||
10140 |
void printOriginalExpression() const { |
||
10141 |
if( result.hasExpression() ) { |
||
10142 |
stream << " " << result.getExpression(); |
||
10143 |
} |
||
10144 |
} |
||
10145 |
|||
10146 |
void printReconstructedExpression() const { |
||
10147 |
if( result.hasExpandedExpression() ) { |
||
10148 |
{ |
||
10149 |
Colour colour( dimColour() ); |
||
10150 |
stream << " for: "; |
||
10151 |
} |
||
10152 |
stream << result.getExpandedExpression(); |
||
10153 |
} |
||
10154 |
} |
||
10155 |
|||
10156 |
void printMessage() { |
||
10157 |
if ( itMessage != messages.end() ) { |
||
10158 |
stream << " '" << itMessage->message << "'"; |
||
10159 |
++itMessage; |
||
10160 |
} |
||
10161 |
} |
||
10162 |
|||
10163 |
void printRemainingMessages( Colour::Code colour = dimColour() ) { |
||
10164 |
if ( itMessage == messages.end() ) |
||
10165 |
return; |
||
10166 |
|||
10167 |
// using messages.end() directly yields compilation error: |
||
10168 |
std::vector<MessageInfo>::const_iterator itEnd = messages.end(); |
||
10169 |
const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) ); |
||
10170 |
|||
10171 |
{ |
||
10172 |
Colour colourGuard( colour ); |
||
10173 |
stream << " with " << pluralise( N, "message" ) << ":"; |
||
10174 |
} |
||
10175 |
|||
10176 |
for(; itMessage != itEnd; ) { |
||
10177 |
// If this assertion is a warning ignore any INFO messages |
||
10178 |
if( printInfoMessages || itMessage->type != ResultWas::Info ) { |
||
10179 |
stream << " '" << itMessage->message << "'"; |
||
10180 |
if ( ++itMessage != itEnd ) { |
||
10181 |
Colour colourGuard( dimColour() ); |
||
10182 |
stream << " and"; |
||
10183 |
} |
||
10184 |
} |
||
10185 |
} |
||
10186 |
} |
||
10187 |
|||
10188 |
private: |
||
10189 |
std::ostream& stream; |
||
10190 |
AssertionStats const& stats; |
||
10191 |
AssertionResult const& result; |
||
10192 |
std::vector<MessageInfo> messages; |
||
10193 |
std::vector<MessageInfo>::const_iterator itMessage; |
||
10194 |
bool printInfoMessages; |
||
10195 |
}; |
||
10196 |
|||
10197 |
// Colour, message variants: |
||
10198 |
// - white: No tests ran. |
||
10199 |
// - red: Failed [both/all] N test cases, failed [both/all] M assertions. |
||
10200 |
// - white: Passed [both/all] N test cases (no assertions). |
||
10201 |
// - red: Failed N tests cases, failed M assertions. |
||
10202 |
// - green: Passed [both/all] N tests cases with M assertions. |
||
10203 |
|||
10204 |
std::string bothOrAll( std::size_t count ) const { |
||
10205 |
return count == 1 ? "" : count == 2 ? "both " : "all " ; |
||
10206 |
} |
||
10207 |
|||
10208 |
void printTotals( const Totals& totals ) const { |
||
10209 |
if( totals.testCases.total() == 0 ) { |
||
10210 |
stream << "No tests ran."; |
||
10211 |
} |
||
10212 |
else if( totals.testCases.failed == totals.testCases.total() ) { |
||
10213 |
Colour colour( Colour::ResultError ); |
||
10214 |
const std::string qualify_assertions_failed = |
||
10215 |
totals.assertions.failed == totals.assertions.total() ? |
||
10216 |
bothOrAll( totals.assertions.failed ) : ""; |
||
10217 |
stream << |
||
10218 |
"Failed " << bothOrAll( totals.testCases.failed ) |
||
10219 |
<< pluralise( totals.testCases.failed, "test case" ) << ", " |
||
10220 |
"failed " << qualify_assertions_failed << |
||
10221 |
pluralise( totals.assertions.failed, "assertion" ) << "."; |
||
10222 |
} |
||
10223 |
else if( totals.assertions.total() == 0 ) { |
||
10224 |
stream << |
||
10225 |
"Passed " << bothOrAll( totals.testCases.total() ) |
||
10226 |
<< pluralise( totals.testCases.total(), "test case" ) |
||
10227 |
<< " (no assertions)."; |
||
10228 |
} |
||
10229 |
else if( totals.assertions.failed ) { |
||
10230 |
Colour colour( Colour::ResultError ); |
||
10231 |
stream << |
||
10232 |
"Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " |
||
10233 |
"failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; |
||
10234 |
} |
||
10235 |
else { |
||
10236 |
Colour colour( Colour::ResultSuccess ); |
||
10237 |
stream << |
||
10238 |
"Passed " << bothOrAll( totals.testCases.passed ) |
||
10239 |
<< pluralise( totals.testCases.passed, "test case" ) << |
||
10240 |
" with " << pluralise( totals.assertions.passed, "assertion" ) << "."; |
||
10241 |
} |
||
10242 |
} |
||
10243 |
}; |
||
10244 |
|||
10245 |
✓✗ | 4 |
INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) |
10246 |
|||
10247 |
} // end namespace Catch |
||
10248 |
|||
10249 |
namespace Catch { |
||
10250 |
// These are all here to avoid warnings about not having any out of line |
||
10251 |
// virtual methods |
||
10252 |
NonCopyable::~NonCopyable() {} |
||
10253 |
1621 |
IShared::~IShared() {} |
|
10254 |
IStream::~IStream() CATCH_NOEXCEPT {} |
||
10255 |
FileStream::~FileStream() CATCH_NOEXCEPT {} |
||
10256 |
2 |
CoutStream::~CoutStream() CATCH_NOEXCEPT {} |
|
10257 |
DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} |
||
10258 |
StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} |
||
10259 |
IContext::~IContext() {} |
||
10260 |
IResultCapture::~IResultCapture() {} |
||
10261 |
788 |
ITestCase::~ITestCase() {} |
|
10262 |
ITestCaseRegistry::~ITestCaseRegistry() {} |
||
10263 |
IRegistryHub::~IRegistryHub() {} |
||
10264 |
IMutableRegistryHub::~IMutableRegistryHub() {} |
||
10265 |
IExceptionTranslator::~IExceptionTranslator() {} |
||
10266 |
IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} |
||
10267 |
IReporter::~IReporter() {} |
||
10268 |
8 |
IReporterFactory::~IReporterFactory() {} |
|
10269 |
IReporterRegistry::~IReporterRegistry() {} |
||
10270 |
2 |
IStreamingReporter::~IStreamingReporter() {} |
|
10271 |
2865846 |
AssertionStats::~AssertionStats() {} |
|
10272 |
1145 |
SectionStats::~SectionStats() {} |
|
10273 |
1182 |
TestCaseStats::~TestCaseStats() {} |
|
10274 |
2 |
TestGroupStats::~TestGroupStats() {} |
|
10275 |
2 |
TestRunStats::~TestRunStats() {} |
|
10276 |
CumulativeReporterBase::SectionNode::~SectionNode() {} |
||
10277 |
CumulativeReporterBase::~CumulativeReporterBase() {} |
||
10278 |
|||
10279 |
6 |
StreamingReporterBase::~StreamingReporterBase() {} |
|
10280 |
1 |
ConsoleReporter::~ConsoleReporter() {} |
|
10281 |
CompactReporter::~CompactReporter() {} |
||
10282 |
IRunner::~IRunner() {} |
||
10283 |
1 |
IMutableContext::~IMutableContext() {} |
|
10284 |
2 |
IConfig::~IConfig() {} |
|
10285 |
XmlReporter::~XmlReporter() {} |
||
10286 |
JunitReporter::~JunitReporter() {} |
||
10287 |
1 |
TestRegistry::~TestRegistry() {} |
|
10288 |
788 |
FreeFunctionTestCase::~FreeFunctionTestCase() {} |
|
10289 |
IGeneratorInfo::~IGeneratorInfo() {} |
||
10290 |
IGeneratorsForTest::~IGeneratorsForTest() {} |
||
10291 |
WildcardPattern::~WildcardPattern() {} |
||
10292 |
4 |
TestSpec::Pattern::~Pattern() {} |
|
10293 |
TestSpec::NamePattern::~NamePattern() {} |
||
10294 |
3 |
TestSpec::TagPattern::~TagPattern() {} |
|
10295 |
3 |
TestSpec::ExcludedPattern::~ExcludedPattern() {} |
|
10296 |
|||
10297 |
Matchers::Impl::StdString::Equals::~Equals() {} |
||
10298 |
Matchers::Impl::StdString::Contains::~Contains() {} |
||
10299 |
Matchers::Impl::StdString::StartsWith::~StartsWith() {} |
||
10300 |
Matchers::Impl::StdString::EndsWith::~EndsWith() {} |
||
10301 |
|||
10302 |
void Config::dummy() {} |
||
10303 |
|||
10304 |
namespace TestCaseTracking { |
||
10305 |
2376 |
ITracker::~ITracker() {} |
|
10306 |
3564 |
TrackerBase::~TrackerBase() {} |
|
10307 |
1188 |
SectionTracker::~SectionTracker() {} |
|
10308 |
IndexTracker::~IndexTracker() {} |
||
10309 |
} |
||
10310 |
} |
||
10311 |
|||
10312 |
#ifdef __clang__ |
||
10313 |
#pragma clang diagnostic pop |
||
10314 |
#endif |
||
10315 |
|||
10316 |
#endif |
||
10317 |
|||
10318 |
#ifdef CATCH_CONFIG_MAIN |
||
10319 |
// #included from: internal/catch_default_main.hpp |
||
10320 |
#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED |
||
10321 |
|||
10322 |
#ifndef __OBJC__ |
||
10323 |
|||
10324 |
// Standard C/C++ main entry point |
||
10325 |
int main (int argc, char * argv[]) { |
||
10326 |
return Catch::Session().run( argc, argv ); |
||
10327 |
} |
||
10328 |
|||
10329 |
#else // __OBJC__ |
||
10330 |
|||
10331 |
// Objective-C entry point |
||
10332 |
int main (int argc, char * const argv[]) { |
||
10333 |
#if !CATCH_ARC_ENABLED |
||
10334 |
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; |
||
10335 |
#endif |
||
10336 |
|||
10337 |
Catch::registerTestMethods(); |
||
10338 |
int result = Catch::Session().run( argc, (char* const*)argv ); |
||
10339 |
|||
10340 |
#if !CATCH_ARC_ENABLED |
||
10341 |
[pool drain]; |
||
10342 |
#endif |
||
10343 |
|||
10344 |
return result; |
||
10345 |
} |
||
10346 |
|||
10347 |
#endif // __OBJC__ |
||
10348 |
|||
10349 |
#endif |
||
10350 |
|||
10351 |
#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED |
||
10352 |
# undef CLARA_CONFIG_MAIN |
||
10353 |
#endif |
||
10354 |
|||
10355 |
////// |
||
10356 |
|||
10357 |
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ |
||
10358 |
#ifdef CATCH_CONFIG_PREFIX_ALL |
||
10359 |
|||
10360 |
#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) |
||
10361 |
#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) |
||
10362 |
|||
10363 |
#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) |
||
10364 |
#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) |
||
10365 |
#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) |
||
10366 |
#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) |
||
10367 |
|||
10368 |
#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) |
||
10369 |
#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) |
||
10370 |
#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) |
||
10371 |
#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) |
||
10372 |
#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) |
||
10373 |
|||
10374 |
#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) |
||
10375 |
#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) |
||
10376 |
#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) |
||
10377 |
#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) |
||
10378 |
|||
10379 |
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) |
||
10380 |
#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) |
||
10381 |
|||
10382 |
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) |
||
10383 |
#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) |
||
10384 |
#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) |
||
10385 |
#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) |
||
10386 |
#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) |
||
10387 |
|||
10388 |
#ifdef CATCH_CONFIG_VARIADIC_MACROS |
||
10389 |
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) |
||
10390 |
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) |
||
10391 |
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) |
||
10392 |
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) |
||
10393 |
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) |
||
10394 |
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) |
||
10395 |
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) |
||
10396 |
#else |
||
10397 |
#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) |
||
10398 |
#define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) |
||
10399 |
#define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) |
||
10400 |
#define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) |
||
10401 |
#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) |
||
10402 |
#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) |
||
10403 |
#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) |
||
10404 |
#endif |
||
10405 |
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) |
||
10406 |
|||
10407 |
#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) |
||
10408 |
#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) |
||
10409 |
|||
10410 |
#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) |
||
10411 |
|||
10412 |
// "BDD-style" convenience wrappers |
||
10413 |
#ifdef CATCH_CONFIG_VARIADIC_MACROS |
||
10414 |
#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) |
||
10415 |
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) |
||
10416 |
#else |
||
10417 |
#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) |
||
10418 |
#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) |
||
10419 |
#endif |
||
10420 |
#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) |
||
10421 |
#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) |
||
10422 |
#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) |
||
10423 |
#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) |
||
10424 |
#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) |
||
10425 |
|||
10426 |
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required |
||
10427 |
#else |
||
10428 |
|||
10429 |
#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) |
||
10430 |
#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) |
||
10431 |
|||
10432 |
#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) |
||
10433 |
#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) |
||
10434 |
#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) |
||
10435 |
#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) |
||
10436 |
|||
10437 |
#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) |
||
10438 |
#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) |
||
10439 |
#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) |
||
10440 |
#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) |
||
10441 |
#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) |
||
10442 |
|||
10443 |
#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) |
||
10444 |
#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) |
||
10445 |
#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) |
||
10446 |
#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) |
||
10447 |
|||
10448 |
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) |
||
10449 |
#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) |
||
10450 |
|||
10451 |
#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) |
||
10452 |
#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) |
||
10453 |
#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) |
||
10454 |
#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) |
||
10455 |
#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) |
||
10456 |
|||
10457 |
#ifdef CATCH_CONFIG_VARIADIC_MACROS |
||
10458 |
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) |
||
10459 |
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) |
||
10460 |
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) |
||
10461 |
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) |
||
10462 |
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) |
||
10463 |
#define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) |
||
10464 |
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) |
||
10465 |
#else |
||
10466 |
#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) |
||
10467 |
#define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) |
||
10468 |
#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) |
||
10469 |
#define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) |
||
10470 |
#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) |
||
10471 |
#define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) |
||
10472 |
#define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) |
||
10473 |
#endif |
||
10474 |
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) |
||
10475 |
|||
10476 |
#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) |
||
10477 |
#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) |
||
10478 |
|||
10479 |
#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) |
||
10480 |
|||
10481 |
#endif |
||
10482 |
|||
10483 |
#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) |
||
10484 |
|||
10485 |
// "BDD-style" convenience wrappers |
||
10486 |
#ifdef CATCH_CONFIG_VARIADIC_MACROS |
||
10487 |
#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) |
||
10488 |
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) |
||
10489 |
#else |
||
10490 |
#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) |
||
10491 |
#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) |
||
10492 |
#endif |
||
10493 |
#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) |
||
10494 |
#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) |
||
10495 |
#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) |
||
10496 |
#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) |
||
10497 |
#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) |
||
10498 |
|||
10499 |
using Catch::Detail::Approx; |
||
10500 |
|||
10501 |
#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED |
||
10502 |
Generated by: GCOVR (Version 3.3) |