1 /*
2 * Catch v1.5.6
3 * Generated: 2016-06-09 19:20:41.460328
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 // #included from: catch_compiler_capabilities.h
79 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
80
81 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler
82 // The following features are defined:
83 //
84 // CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
85 // CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
86 // CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
87 // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
88 // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
89 // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
90 // CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
91 // CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
92
93 // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
94
95 // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
96 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
97 // ****************
98 // Note to maintainers: if new toggles are added please document them
99 // in configuration.md, too
100 // ****************
101
102 // In general each macro has a _NO_<feature name> form
103 // (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
104 // Many features, at point of detection, define an _INTERNAL_ macro, so they
105 // can be combined, en-mass, with the _NO_ forms later.
106
107 // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
108
109 #ifdef __cplusplus
110
111 # if __cplusplus >= 201103L
112 # define CATCH_CPP11_OR_GREATER
113 # endif
114
115 # if __cplusplus >= 201402L
116 # define CATCH_CPP14_OR_GREATER
117 # endif
118
119 #endif
120
121 #ifdef __clang__
122
123 # if __has_feature(cxx_nullptr)
124 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
125 # endif
126
127 # if __has_feature(cxx_noexcept)
128 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
129 # endif
130
131 # if defined(CATCH_CPP11_OR_GREATER)
132 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
133 # endif
134
135 #endif // __clang__
136
137 ////////////////////////////////////////////////////////////////////////////////
138 // Borland
139 #ifdef __BORLANDC__
140
141 #endif // __BORLANDC__
142
143 ////////////////////////////////////////////////////////////////////////////////
144 // EDG
145 #ifdef __EDG_VERSION__
146
147 #endif // __EDG_VERSION__
148
149 ////////////////////////////////////////////////////////////////////////////////
150 // Digital Mars
151 #ifdef __DMC__
152
153 #endif // __DMC__
154
155 ////////////////////////////////////////////////////////////////////////////////
156 // GCC
157 #ifdef __GNUC__
158
159 # if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
160 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
161 # endif
162
163 # if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER)
164 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
165 # endif
166
167 // - otherwise more recent versions define __cplusplus >= 201103L
168 // and will get picked up below
169
170 #endif // __GNUC__
171
172 ////////////////////////////////////////////////////////////////////////////////
173 // Visual C++
174 #ifdef _MSC_VER
175
176 #if (_MSC_VER >= 1600)
177 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
178 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
179 #endif
180
181 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
182 #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
183 #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
184 #endif
185
186 #endif // _MSC_VER
187
188 ////////////////////////////////////////////////////////////////////////////////
189
190 // Use variadic macros if the compiler supports them
191 #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
192 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
193 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
194 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
195
196 #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
197
198 #endif
199
200 // Use __COUNTER__ if the compiler supports it
201 #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
202 ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
203 ( defined __clang__ && __clang_major__ >= 3 )
204
205 #define CATCH_INTERNAL_CONFIG_COUNTER
206
207 #endif
208
209 ////////////////////////////////////////////////////////////////////////////////
210 // C++ language feature support
211
212 // catch all support for C++11
213 #if defined(CATCH_CPP11_OR_GREATER)
214
215 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
216 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
217 # endif
218
219 # ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
220 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
221 # endif
222
223 # ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
224 # define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
225 # endif
226
227 # ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
228 # define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
229 # endif
230
231 # ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
232 # define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
233 # endif
234
235 # ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
236 # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
237 # endif
238
239 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
240 # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
241 # endif
242
243 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
244 # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
245 # endif
246 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
247 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
248 # endif
249
250 #endif // __cplusplus >= 201103L
251
252 // Now set the actual defines based on the above + anything the user has configured
253 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
254 # define CATCH_CONFIG_CPP11_NULLPTR
255 #endif
256 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
257 # define CATCH_CONFIG_CPP11_NOEXCEPT
258 #endif
259 #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)
260 # define CATCH_CONFIG_CPP11_GENERATED_METHODS
261 #endif
262 #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)
263 # define CATCH_CONFIG_CPP11_IS_ENUM
264 #endif
265 #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
266 # define CATCH_CONFIG_CPP11_TUPLE
267 #endif
268 #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
269 # define CATCH_CONFIG_VARIADIC_MACROS
270 #endif
271 #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)
272 # define CATCH_CONFIG_CPP11_LONG_LONG
273 #endif
274 #if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
275 # define CATCH_CONFIG_CPP11_OVERRIDE
276 #endif
277 #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)
278 # define CATCH_CONFIG_CPP11_UNIQUE_PTR
279 #endif
280 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
281 # define CATCH_CONFIG_COUNTER
282 #endif
283
284 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
285 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
286 #endif
287
288 // noexcept support:
289 #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
290 # define CATCH_NOEXCEPT noexcept
291 # define CATCH_NOEXCEPT_IS(x) noexcept(x)
292 #else
293 # define CATCH_NOEXCEPT throw()
294 # define CATCH_NOEXCEPT_IS(x)
295 #endif
296
297 // nullptr support
298 #ifdef CATCH_CONFIG_CPP11_NULLPTR
299 # define CATCH_NULL nullptr
300 #else
301 # define CATCH_NULL NULL
302 #endif
303
304 // override support
305 #ifdef CATCH_CONFIG_CPP11_OVERRIDE
306 # define CATCH_OVERRIDE override
307 #else
308 # define CATCH_OVERRIDE
309 #endif
310
311 // unique_ptr support
312 #ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
313 # define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
314 #else
315 # define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
316 #endif
317
318 namespace Catch {
319
320 struct IConfig;
321
322 struct CaseSensitive {
323 enum Choice {
324 Yes,
325 No
326 };
327 };
328
329 class NonCopyable {
330 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
331 NonCopyable(NonCopyable const&) = delete;
332 NonCopyable(NonCopyable &&) = delete;
333 NonCopyable& operator = (NonCopyable const&) = delete;
334 NonCopyable& operator = (NonCopyable &&) = delete;
335 #else
336 NonCopyable(NonCopyable const& info);
337 NonCopyable& operator = (NonCopyable const&);
338 #endif
339
340 protected:
NonCopyable()341 NonCopyable() {}
342 virtual ~NonCopyable();
343 };
344
345 class SafeBool {
346 public:
347 typedef void (SafeBool::*type)() const;
348
makeSafe(bool value)349 static type makeSafe(bool value) {
350 return value ? &SafeBool::trueValue : 0;
351 }
352 private:
trueValue() const353 void trueValue() const {}
354 };
355
356 template<typename ContainerT>
deleteAll(ContainerT & container)357 inline void deleteAll(ContainerT& container) {
358 typename ContainerT::const_iterator it = container.begin();
359 typename ContainerT::const_iterator itEnd = container.end();
360 for (; it != itEnd; ++it)
361 delete *it;
362 }
363 template<typename AssociativeContainerT>
deleteAllValues(AssociativeContainerT & container)364 inline void deleteAllValues(AssociativeContainerT& container) {
365 typename AssociativeContainerT::const_iterator it = container.begin();
366 typename AssociativeContainerT::const_iterator itEnd = container.end();
367 for (; it != itEnd; ++it)
368 delete it->second;
369 }
370
371 bool startsWith(std::string const& s, std::string const& prefix);
372 bool endsWith(std::string const& s, std::string const& suffix);
373 bool contains(std::string const& s, std::string const& infix);
374 void toLowerInPlace(std::string& s);
375 std::string toLower(std::string const& s);
376 std::string trim(std::string const& str);
377 bool replaceInPlace(std::string& str, std::string const& replaceThis, std::string const& withThis);
378
379 struct pluralise {
380 pluralise(std::size_t count, std::string const& label);
381
382 friend std::ostream& operator << (std::ostream& os, pluralise const& pluraliser);
383
384 std::size_t m_count;
385 std::string m_label;
386 };
387
388 struct SourceLineInfo {
389
390 SourceLineInfo();
391 SourceLineInfo(char const* _file, std::size_t _line);
392 SourceLineInfo(SourceLineInfo const& other);
393 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
394 SourceLineInfo(SourceLineInfo &&) = default;
395 SourceLineInfo& operator = (SourceLineInfo const&) = default;
396 SourceLineInfo& operator = (SourceLineInfo &&) = default;
397 # endif
398 bool empty() const;
399 bool operator == (SourceLineInfo const& other) const;
400 bool operator < (SourceLineInfo const& other) const;
401
402 std::string file;
403 std::size_t line;
404 };
405
406 std::ostream& operator << (std::ostream& os, SourceLineInfo const& info);
407
408 // This is just here to avoid compiler warnings with macro constants and boolean literals
isTrue(bool value)409 inline bool isTrue(bool value){ return value; }
alwaysTrue()410 inline bool alwaysTrue() { return true; }
alwaysFalse()411 inline bool alwaysFalse() { return false; }
412
413 void throwLogicError(std::string const& message, SourceLineInfo const& locationInfo);
414
415 void seedRng(IConfig const& config);
416 unsigned int rngSeed();
417
418 // Use this in variadic streaming macros to allow
419 // >> +StreamEndStop
420 // as well as
421 // >> stuff +StreamEndStop
422 struct StreamEndStop {
operator +Catch::StreamEndStop423 std::string operator+() {
424 return std::string();
425 }
426 };
427 template<typename T>
operator +(T const & value,StreamEndStop)428 T const& operator + (T const& value, StreamEndStop) {
429 return value;
430 }
431 }
432
433 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
434 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
435
436 #include <ostream>
437
438 namespace Catch {
439
440 class NotImplementedException : public std::exception
441 {
442 public:
443 NotImplementedException(SourceLineInfo const& lineInfo);
NotImplementedException(NotImplementedException const &)444 NotImplementedException(NotImplementedException const&) {}
445
~NotImplementedException()446 virtual ~NotImplementedException() CATCH_NOEXCEPT{}
447
448 virtual const char* what() const CATCH_NOEXCEPT;
449
450 private:
451 std::string m_what;
452 SourceLineInfo m_lineInfo;
453 };
454
455 } // end namespace Catch
456
457 ///////////////////////////////////////////////////////////////////////////////
458 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
459
460 // #included from: internal/catch_context.h
461 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
462
463 // #included from: catch_interfaces_generators.h
464 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
465
466 #include <string>
467
468 namespace Catch {
469
470 struct IGeneratorInfo {
471 virtual ~IGeneratorInfo();
472 virtual bool moveNext() = 0;
473 virtual std::size_t getCurrentIndex() const = 0;
474 };
475
476 struct IGeneratorsForTest {
477 virtual ~IGeneratorsForTest();
478
479 virtual IGeneratorInfo& getGeneratorInfo(std::string const& fileInfo, std::size_t size) = 0;
480 virtual bool moveNext() = 0;
481 };
482
483 IGeneratorsForTest* createGeneratorsForTest();
484
485 } // end namespace Catch
486
487 // #included from: catch_ptr.hpp
488 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
489
490 #ifdef __clang__
491 #pragma clang diagnostic push
492 #pragma clang diagnostic ignored "-Wpadded"
493 #endif
494
495 namespace Catch {
496
497 // An intrusive reference counting smart pointer.
498 // T must implement addRef() and release() methods
499 // typically implementing the IShared interface
500 template<typename T>
501 class Ptr {
502 public:
Ptr()503 Ptr() : m_p(CATCH_NULL){}
Ptr(T * p)504 Ptr(T* p) : m_p(p){
505 if (m_p)
506 m_p->addRef();
507 }
Ptr(Ptr const & other)508 Ptr(Ptr const& other) : m_p(other.m_p){
509 if (m_p)
510 m_p->addRef();
511 }
~Ptr()512 ~Ptr(){
513 if (m_p)
514 m_p->release();
515 }
reset()516 void reset() {
517 if (m_p)
518 m_p->release();
519 m_p = CATCH_NULL;
520 }
operator =(T * p)521 Ptr& operator = (T* p){
522 Ptr temp(p);
523 swap(temp);
524 return *this;
525 }
operator =(Ptr const & other)526 Ptr& operator = (Ptr const& other){
527 Ptr temp(other);
528 swap(temp);
529 return *this;
530 }
swap(Ptr & other)531 void swap(Ptr& other) { std::swap(m_p, other.m_p); }
get() const532 T* get() const{ return m_p; }
operator *() const533 T& operator*() const { return *m_p; }
operator ->() const534 T* operator->() const { return m_p; }
operator !() const535 bool operator !() const { return m_p == CATCH_NULL; }
operator SafeBool::type() const536 operator SafeBool::type() const { return SafeBool::makeSafe(m_p != CATCH_NULL); }
537
538 private:
539 T* m_p;
540 };
541
542 struct IShared : NonCopyable {
543 virtual ~IShared();
544 virtual void addRef() const = 0;
545 virtual void release() const = 0;
546 };
547
548 template<typename T = IShared>
549 struct SharedImpl : T {
550
SharedImplCatch::SharedImpl551 SharedImpl() : m_rc(0){}
552
addRefCatch::SharedImpl553 virtual void addRef() const {
554 ++m_rc;
555 }
releaseCatch::SharedImpl556 virtual void release() const {
557 if (--m_rc == 0)
558 delete this;
559 }
560
561 mutable unsigned int m_rc;
562 };
563
564 } // end namespace Catch
565
566 #ifdef __clang__
567 #pragma clang diagnostic pop
568 #endif
569
570 #include <memory>
571 #include <vector>
572 #include <stdlib.h>
573
574 namespace Catch {
575
576 class TestCase;
577 class Stream;
578 struct IResultCapture;
579 struct IRunner;
580 struct IGeneratorsForTest;
581 struct IConfig;
582
583 struct IContext
584 {
585 virtual ~IContext();
586
587 virtual IResultCapture* getResultCapture() = 0;
588 virtual IRunner* getRunner() = 0;
589 virtual size_t getGeneratorIndex(std::string const& fileInfo, size_t totalSize) = 0;
590 virtual bool advanceGeneratorsForCurrentTest() = 0;
591 virtual Ptr<IConfig const> getConfig() const = 0;
592 };
593
594 struct IMutableContext : IContext
595 {
596 virtual ~IMutableContext();
597 virtual void setResultCapture(IResultCapture* resultCapture) = 0;
598 virtual void setRunner(IRunner* runner) = 0;
599 virtual void setConfig(Ptr<IConfig const> const& config) = 0;
600 };
601
602 IContext& getCurrentContext();
603 IMutableContext& getCurrentMutableContext();
604 void cleanUpContext();
605 Stream createStream(std::string const& streamName);
606
607 }
608
609 // #included from: internal/catch_test_registry.hpp
610 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
611
612 // #included from: catch_interfaces_testcase.h
613 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
614
615 #include <vector>
616
617 namespace Catch {
618
619 class TestSpec;
620
621 struct ITestCase : IShared {
622 virtual void invoke() const = 0;
623 protected:
624 virtual ~ITestCase();
625 };
626
627 class TestCase;
628 struct IConfig;
629
630 struct ITestCaseRegistry {
631 virtual ~ITestCaseRegistry();
632 virtual std::vector<TestCase> const& getAllTests() const = 0;
633 virtual std::vector<TestCase> const& getAllTestsSorted(IConfig const& config) const = 0;
634 };
635
636 bool matchTest(TestCase const& testCase, TestSpec const& testSpec, IConfig const& config);
637 std::vector<TestCase> filterTests(std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config);
638 std::vector<TestCase> const& getAllTestCasesSorted(IConfig const& config);
639
640 }
641
642 namespace Catch {
643
644 template<typename C>
645 class MethodTestCase : public SharedImpl<ITestCase> {
646
647 public:
MethodTestCase(void (C::* method)())648 MethodTestCase(void (C::*method)()) : m_method(method) {}
649
invoke() const650 virtual void invoke() const {
651 C obj;
652 (obj.*m_method)();
653 }
654
655 private:
~MethodTestCase()656 virtual ~MethodTestCase() {}
657
658 void (C::*m_method)();
659 };
660
661 typedef void(*TestFunction)();
662
663 struct NameAndDesc {
NameAndDescCatch::NameAndDesc664 NameAndDesc(const char* _name = "", const char* _description = "")
665 : name(_name), description(_description)
666 {}
667
668 const char* name;
669 const char* description;
670 };
671
672 void registerTestCase
673 (ITestCase* testCase,
674 char const* className,
675 NameAndDesc const& nameAndDesc,
676 SourceLineInfo const& lineInfo);
677
678 struct AutoReg {
679
680 AutoReg
681 (TestFunction function,
682 SourceLineInfo const& lineInfo,
683 NameAndDesc const& nameAndDesc);
684
685 template<typename C>
AutoRegCatch::AutoReg686 AutoReg
687 (void (C::*method)(),
688 char const* className,
689 NameAndDesc const& nameAndDesc,
690 SourceLineInfo const& lineInfo) {
691
692 registerTestCase
693 (new MethodTestCase<C>(method),
694 className,
695 nameAndDesc,
696 lineInfo);
697 }
698
699 ~AutoReg();
700
701 private:
702 AutoReg(AutoReg const&);
703 void operator= (AutoReg const&);
704 };
705
706 void registerTestCaseFunction
707 (TestFunction function,
708 SourceLineInfo const& lineInfo,
709 NameAndDesc const& nameAndDesc);
710
711 } // end namespace Catch
712
713 #ifdef CATCH_CONFIG_VARIADIC_MACROS
714 ///////////////////////////////////////////////////////////////////////////////
715 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
716 static void TestName(); \
717 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
718 static void TestName()
719 #define INTERNAL_CATCH_TESTCASE( ... ) \
720 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
721
722 ///////////////////////////////////////////////////////////////////////////////
723 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
724 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
725
726 ///////////////////////////////////////////////////////////////////////////////
727 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
728 namespace{ \
729 struct TestName : ClassName{ \
730 void test(); \
731 }; \
732 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
733 } \
734 void TestName::test()
735 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
736 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
737
738 ///////////////////////////////////////////////////////////////////////////////
739 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
740 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
741
742 #else
743 ///////////////////////////////////////////////////////////////////////////////
744 #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
745 static void TestName(); \
746 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
747 static void TestName()
748 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
749 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
750
751 ///////////////////////////////////////////////////////////////////////////////
752 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
753 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
754
755 ///////////////////////////////////////////////////////////////////////////////
756 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
757 namespace{ \
758 struct TestCaseName : ClassName{ \
759 void test(); \
760 }; \
761 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
762 } \
763 void TestCaseName::test()
764 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
765 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
766
767 ///////////////////////////////////////////////////////////////////////////////
768 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
769 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
770 #endif
771
772 // #included from: internal/catch_capture.hpp
773 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
774
775 // #included from: catch_result_builder.h
776 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
777
778 // #included from: catch_result_type.h
779 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
780
781 namespace Catch {
782
783 // ResultWas::OfType enum
784 struct ResultWas {
785 enum OfType {
786 Unknown = -1,
787 Ok = 0,
788 Info = 1,
789 Warning = 2,
790
791 FailureBit = 0x10,
792
793 ExpressionFailed = FailureBit | 1,
794 ExplicitFailure = FailureBit | 2,
795
796 Exception = 0x100 | FailureBit,
797
798 ThrewException = Exception | 1,
799 DidntThrowException = Exception | 2,
800
801 FatalErrorCondition = 0x200 | FailureBit
802
803 };
804 };
805
isOk(ResultWas::OfType resultType)806 inline bool isOk(ResultWas::OfType resultType) {
807 return (resultType & ResultWas::FailureBit) == 0;
808 }
isJustInfo(int flags)809 inline bool isJustInfo(int flags) {
810 return flags == ResultWas::Info;
811 }
812
813 // ResultDisposition::Flags enum
814 struct ResultDisposition {
815 enum Flags {
816 Normal = 0x01,
817
818 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
819 FalseTest = 0x04, // Prefix expression with !
820 SuppressFail = 0x08 // Failures are reported but do not fail the test
821 };
822 };
823
operator |(ResultDisposition::Flags lhs,ResultDisposition::Flags rhs)824 inline ResultDisposition::Flags operator | (ResultDisposition::Flags lhs, ResultDisposition::Flags rhs) {
825 return static_cast<ResultDisposition::Flags>(static_cast<int>(lhs) | static_cast<int>(rhs));
826 }
827
shouldContinueOnFailure(int flags)828 inline bool shouldContinueOnFailure(int flags) { return (flags & ResultDisposition::ContinueOnFailure) != 0; }
isFalseTest(int flags)829 inline bool isFalseTest(int flags) { return (flags & ResultDisposition::FalseTest) != 0; }
shouldSuppressFailure(int flags)830 inline bool shouldSuppressFailure(int flags) { return (flags & ResultDisposition::SuppressFail) != 0; }
831
832 } // end namespace Catch
833
834 // #included from: catch_assertionresult.h
835 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
836
837 #include <string>
838
839 namespace Catch {
840
841 struct AssertionInfo
842 {
AssertionInfoCatch::AssertionInfo843 AssertionInfo() {}
844 AssertionInfo(std::string const& _macroName,
845 SourceLineInfo const& _lineInfo,
846 std::string const& _capturedExpression,
847 ResultDisposition::Flags _resultDisposition);
848
849 std::string macroName;
850 SourceLineInfo lineInfo;
851 std::string capturedExpression;
852 ResultDisposition::Flags resultDisposition;
853 };
854
855 struct AssertionResultData
856 {
AssertionResultDataCatch::AssertionResultData857 AssertionResultData() : resultType(ResultWas::Unknown) {}
858
859 std::string reconstructedExpression;
860 std::string message;
861 ResultWas::OfType resultType;
862 };
863
864 class AssertionResult {
865 public:
866 AssertionResult();
867 AssertionResult(AssertionInfo const& info, AssertionResultData const& data);
868 ~AssertionResult();
869 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
870 AssertionResult(AssertionResult const&) = default;
871 AssertionResult(AssertionResult &&) = default;
872 AssertionResult& operator = (AssertionResult const&) = default;
873 AssertionResult& operator = (AssertionResult &&) = default;
874 # endif
875
876 bool isOk() const;
877 bool succeeded() const;
878 ResultWas::OfType getResultType() const;
879 bool hasExpression() const;
880 bool hasMessage() const;
881 std::string getExpression() const;
882 std::string getExpressionInMacro() const;
883 bool hasExpandedExpression() const;
884 std::string getExpandedExpression() const;
885 std::string getMessage() const;
886 SourceLineInfo getSourceInfo() const;
887 std::string getTestMacroName() const;
888
889 protected:
890 AssertionInfo m_info;
891 AssertionResultData m_resultData;
892 };
893
894 } // end namespace Catch
895
896 // #included from: catch_matchers.hpp
897 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
898
899 namespace Catch {
900 namespace Matchers {
901 namespace Impl {
902
903 namespace Generic {
904 template<typename ExpressionT> class AllOf;
905 template<typename ExpressionT> class AnyOf;
906 template<typename ExpressionT> class Not;
907 }
908
909 template<typename ExpressionT>
910 struct Matcher : SharedImpl<IShared>
911 {
912 typedef ExpressionT ExpressionType;
913
~MatcherCatch::Matchers::Impl::Matcher914 virtual ~Matcher() {}
915 virtual Ptr<Matcher> clone() const = 0;
916 virtual bool match(ExpressionT const& expr) const = 0;
917 virtual std::string toString() const = 0;
918
919 Generic::AllOf<ExpressionT> operator && (Matcher<ExpressionT> const& other) const;
920 Generic::AnyOf<ExpressionT> operator || (Matcher<ExpressionT> const& other) const;
921 Generic::Not<ExpressionT> operator ! () const;
922 };
923
924 template<typename DerivedT, typename ExpressionT>
925 struct MatcherImpl : Matcher<ExpressionT> {
926
cloneCatch::Matchers::Impl::MatcherImpl927 virtual Ptr<Matcher<ExpressionT> > clone() const {
928 return Ptr<Matcher<ExpressionT> >(new DerivedT(static_cast<DerivedT const&>(*this)));
929 }
930 };
931
932 namespace Generic {
933 template<typename ExpressionT>
934 class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> {
935 public:
Not(Matcher<ExpressionT> const & matcher)936 explicit Not(Matcher<ExpressionT> const& matcher) : m_matcher(matcher.clone()) {}
Not(Not const & other)937 Not(Not const& other) : m_matcher(other.m_matcher) {}
938
match(ExpressionT const & expr) const939 virtual bool match(ExpressionT const& expr) const CATCH_OVERRIDE{
940 return !m_matcher->match(expr);
941 }
942
toString() const943 virtual std::string toString() const CATCH_OVERRIDE{
944 return "not " + m_matcher->toString();
945 }
946 private:
947 Ptr< Matcher<ExpressionT> > m_matcher;
948 };
949
950 template<typename ExpressionT>
951 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
952 public:
953
AllOf()954 AllOf() {}
AllOf(AllOf const & other)955 AllOf(AllOf const& other) : m_matchers(other.m_matchers) {}
956
add(Matcher<ExpressionT> const & matcher)957 AllOf& add(Matcher<ExpressionT> const& matcher) {
958 m_matchers.push_back(matcher.clone());
959 return *this;
960 }
match(ExpressionT const & expr) const961 virtual bool match(ExpressionT const& expr) const
962 {
963 for (std::size_t i = 0; i < m_matchers.size(); ++i)
964 if (!m_matchers[i]->match(expr))
965 return false;
966 return true;
967 }
toString() const968 virtual std::string toString() const {
969 std::ostringstream oss;
970 oss << "( ";
971 for (std::size_t i = 0; i < m_matchers.size(); ++i) {
972 if (i != 0)
973 oss << " and ";
974 oss << m_matchers[i]->toString();
975 }
976 oss << " )";
977 return oss.str();
978 }
979
operator &&(Matcher<ExpressionT> const & other) const980 AllOf operator && (Matcher<ExpressionT> const& other) const {
981 AllOf allOfExpr(*this);
982 allOfExpr.add(other);
983 return allOfExpr;
984 }
985
986 private:
987 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
988 };
989
990 template<typename ExpressionT>
991 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
992 public:
993
AnyOf()994 AnyOf() {}
AnyOf(AnyOf const & other)995 AnyOf(AnyOf const& other) : m_matchers(other.m_matchers) {}
996
add(Matcher<ExpressionT> const & matcher)997 AnyOf& add(Matcher<ExpressionT> const& matcher) {
998 m_matchers.push_back(matcher.clone());
999 return *this;
1000 }
match(ExpressionT const & expr) const1001 virtual bool match(ExpressionT const& expr) const
1002 {
1003 for (std::size_t i = 0; i < m_matchers.size(); ++i)
1004 if (m_matchers[i]->match(expr))
1005 return true;
1006 return false;
1007 }
toString() const1008 virtual std::string toString() const {
1009 std::ostringstream oss;
1010 oss << "( ";
1011 for (std::size_t i = 0; i < m_matchers.size(); ++i) {
1012 if (i != 0)
1013 oss << " or ";
1014 oss << m_matchers[i]->toString();
1015 }
1016 oss << " )";
1017 return oss.str();
1018 }
1019
operator ||(Matcher<ExpressionT> const & other) const1020 AnyOf operator || (Matcher<ExpressionT> const& other) const {
1021 AnyOf anyOfExpr(*this);
1022 anyOfExpr.add(other);
1023 return anyOfExpr;
1024 }
1025
1026 private:
1027 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
1028 };
1029
1030 } // namespace Generic
1031
1032 template<typename ExpressionT>
operator &&(Matcher<ExpressionT> const & other) const1033 Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && (Matcher<ExpressionT> const& other) const {
1034 Generic::AllOf<ExpressionT> allOfExpr;
1035 allOfExpr.add(*this);
1036 allOfExpr.add(other);
1037 return allOfExpr;
1038 }
1039
1040 template<typename ExpressionT>
operator ||(Matcher<ExpressionT> const & other) const1041 Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || (Matcher<ExpressionT> const& other) const {
1042 Generic::AnyOf<ExpressionT> anyOfExpr;
1043 anyOfExpr.add(*this);
1044 anyOfExpr.add(other);
1045 return anyOfExpr;
1046 }
1047
1048 template<typename ExpressionT>
operator !() const1049 Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const {
1050 return Generic::Not<ExpressionT>(*this);
1051 }
1052
1053 namespace StdString {
1054
makeString(std::string const & str)1055 inline std::string makeString(std::string const& str) { return str; }
makeString(const char * str)1056 inline std::string makeString(const char* str) { return str ? std::string(str) : std::string(); }
1057
1058 struct CasedString
1059 {
CasedStringCatch::Matchers::Impl::StdString::CasedString1060 CasedString(std::string const& str, CaseSensitive::Choice caseSensitivity)
1061 : m_caseSensitivity(caseSensitivity),
1062 m_str(adjustString(str))
1063 {}
adjustStringCatch::Matchers::Impl::StdString::CasedString1064 std::string adjustString(std::string const& str) const {
1065 return m_caseSensitivity == CaseSensitive::No
1066 ? toLower(str)
1067 : str;
1068
1069 }
toStringSuffixCatch::Matchers::Impl::StdString::CasedString1070 std::string toStringSuffix() const
1071 {
1072 return m_caseSensitivity == CaseSensitive::No
1073 ? " (case insensitive)"
1074 : "";
1075 }
1076 CaseSensitive::Choice m_caseSensitivity;
1077 std::string m_str;
1078 };
1079
1080 struct Equals : MatcherImpl<Equals, std::string> {
EqualsCatch::Matchers::Impl::StdString::Equals1081 Equals(std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
1082 : m_data(str, caseSensitivity)
1083 {}
EqualsCatch::Matchers::Impl::StdString::Equals1084 Equals(Equals const& other) : m_data(other.m_data){}
1085
1086 virtual ~Equals();
1087
matchCatch::Matchers::Impl::StdString::Equals1088 virtual bool match(std::string const& expr) const {
1089 return m_data.m_str == m_data.adjustString(expr);;
1090 }
toStringCatch::Matchers::Impl::StdString::Equals1091 virtual std::string toString() const {
1092 return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1093 }
1094
1095 CasedString m_data;
1096 };
1097
1098 struct Contains : MatcherImpl<Contains, std::string> {
ContainsCatch::Matchers::Impl::StdString::Contains1099 Contains(std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
1100 : m_data(substr, caseSensitivity){}
ContainsCatch::Matchers::Impl::StdString::Contains1101 Contains(Contains const& other) : m_data(other.m_data){}
1102
1103 virtual ~Contains();
1104
matchCatch::Matchers::Impl::StdString::Contains1105 virtual bool match(std::string const& expr) const {
1106 return m_data.adjustString(expr).find(m_data.m_str) != std::string::npos;
1107 }
toStringCatch::Matchers::Impl::StdString::Contains1108 virtual std::string toString() const {
1109 return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1110 }
1111
1112 CasedString m_data;
1113 };
1114
1115 struct StartsWith : MatcherImpl<StartsWith, std::string> {
StartsWithCatch::Matchers::Impl::StdString::StartsWith1116 StartsWith(std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
1117 : m_data(substr, caseSensitivity){}
1118
StartsWithCatch::Matchers::Impl::StdString::StartsWith1119 StartsWith(StartsWith const& other) : m_data(other.m_data){}
1120
1121 virtual ~StartsWith();
1122
matchCatch::Matchers::Impl::StdString::StartsWith1123 virtual bool match(std::string const& expr) const {
1124 return startsWith(m_data.adjustString(expr), m_data.m_str);
1125 }
toStringCatch::Matchers::Impl::StdString::StartsWith1126 virtual std::string toString() const {
1127 return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1128 }
1129
1130 CasedString m_data;
1131 };
1132
1133 struct EndsWith : MatcherImpl<EndsWith, std::string> {
EndsWithCatch::Matchers::Impl::StdString::EndsWith1134 EndsWith(std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
1135 : m_data(substr, caseSensitivity){}
EndsWithCatch::Matchers::Impl::StdString::EndsWith1136 EndsWith(EndsWith const& other) : m_data(other.m_data){}
1137
1138 virtual ~EndsWith();
1139
matchCatch::Matchers::Impl::StdString::EndsWith1140 virtual bool match(std::string const& expr) const {
1141 return endsWith(m_data.adjustString(expr), m_data.m_str);
1142 }
toStringCatch::Matchers::Impl::StdString::EndsWith1143 virtual std::string toString() const {
1144 return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1145 }
1146
1147 CasedString m_data;
1148 };
1149 } // namespace StdString
1150 } // namespace Impl
1151
1152 // The following functions create the actual matcher objects.
1153 // This allows the types to be inferred
1154 template<typename ExpressionT>
Not(Impl::Matcher<ExpressionT> const & m)1155 inline Impl::Generic::Not<ExpressionT> Not(Impl::Matcher<ExpressionT> const& m) {
1156 return Impl::Generic::Not<ExpressionT>(m);
1157 }
1158
1159 template<typename ExpressionT>
AllOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2)1160 inline Impl::Generic::AllOf<ExpressionT> AllOf(Impl::Matcher<ExpressionT> const& m1,
1161 Impl::Matcher<ExpressionT> const& m2) {
1162 return Impl::Generic::AllOf<ExpressionT>().add(m1).add(m2);
1163 }
1164 template<typename ExpressionT>
AllOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2,Impl::Matcher<ExpressionT> const & m3)1165 inline Impl::Generic::AllOf<ExpressionT> AllOf(Impl::Matcher<ExpressionT> const& m1,
1166 Impl::Matcher<ExpressionT> const& m2,
1167 Impl::Matcher<ExpressionT> const& m3) {
1168 return Impl::Generic::AllOf<ExpressionT>().add(m1).add(m2).add(m3);
1169 }
1170 template<typename ExpressionT>
AnyOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2)1171 inline Impl::Generic::AnyOf<ExpressionT> AnyOf(Impl::Matcher<ExpressionT> const& m1,
1172 Impl::Matcher<ExpressionT> const& m2) {
1173 return Impl::Generic::AnyOf<ExpressionT>().add(m1).add(m2);
1174 }
1175 template<typename ExpressionT>
AnyOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2,Impl::Matcher<ExpressionT> const & m3)1176 inline Impl::Generic::AnyOf<ExpressionT> AnyOf(Impl::Matcher<ExpressionT> const& m1,
1177 Impl::Matcher<ExpressionT> const& m2,
1178 Impl::Matcher<ExpressionT> const& m3) {
1179 return Impl::Generic::AnyOf<ExpressionT>().add(m1).add(m2).add(m3);
1180 }
1181
Equals(std::string const & str,CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)1182 inline Impl::StdString::Equals Equals(std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) {
1183 return Impl::StdString::Equals(str, caseSensitivity);
1184 }
Equals(const char * str,CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)1185 inline Impl::StdString::Equals Equals(const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) {
1186 return Impl::StdString::Equals(Impl::StdString::makeString(str), caseSensitivity);
1187 }
Contains(std::string const & substr,CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)1188 inline Impl::StdString::Contains Contains(std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) {
1189 return Impl::StdString::Contains(substr, caseSensitivity);
1190 }
Contains(const char * substr,CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)1191 inline Impl::StdString::Contains Contains(const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) {
1192 return Impl::StdString::Contains(Impl::StdString::makeString(substr), caseSensitivity);
1193 }
StartsWith(std::string const & substr)1194 inline Impl::StdString::StartsWith StartsWith(std::string const& substr) {
1195 return Impl::StdString::StartsWith(substr);
1196 }
StartsWith(const char * substr)1197 inline Impl::StdString::StartsWith StartsWith(const char* substr) {
1198 return Impl::StdString::StartsWith(Impl::StdString::makeString(substr));
1199 }
EndsWith(std::string const & substr)1200 inline Impl::StdString::EndsWith EndsWith(std::string const& substr) {
1201 return Impl::StdString::EndsWith(substr);
1202 }
EndsWith(const char * substr)1203 inline Impl::StdString::EndsWith EndsWith(const char* substr) {
1204 return Impl::StdString::EndsWith(Impl::StdString::makeString(substr));
1205 }
1206
1207 } // namespace Matchers
1208
1209 using namespace Matchers;
1210
1211 } // namespace Catch
1212
1213 namespace Catch {
1214
1215 struct TestFailureException{};
1216
1217 template<typename T> class ExpressionLhs;
1218
1219 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1220
1221 struct CopyableStream {
CopyableStreamCatch::CopyableStream1222 CopyableStream() {}
CopyableStreamCatch::CopyableStream1223 CopyableStream(CopyableStream const& other) {
1224 oss << other.oss.str();
1225 }
operator =Catch::CopyableStream1226 CopyableStream& operator=(CopyableStream const& other) {
1227 oss.str("");
1228 oss << other.oss.str();
1229 return *this;
1230 }
1231 std::ostringstream oss;
1232 };
1233
1234 class ResultBuilder {
1235 public:
1236 ResultBuilder(char const* macroName,
1237 SourceLineInfo const& lineInfo,
1238 char const* capturedExpression,
1239 ResultDisposition::Flags resultDisposition,
1240 char const* secondArg = "");
1241
1242 template<typename T>
1243 ExpressionLhs<T const&> operator <= (T const& operand);
1244 ExpressionLhs<bool> operator <= (bool value);
1245
1246 template<typename T>
operator <<(T const & value)1247 ResultBuilder& operator << (T const& value) {
1248 m_stream.oss << value;
1249 return *this;
1250 }
1251
1252 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && (RhsT const&);
1253 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || (RhsT const&);
1254
1255 ResultBuilder& setResultType(ResultWas::OfType result);
1256 ResultBuilder& setResultType(bool result);
1257 ResultBuilder& setLhs(std::string const& lhs);
1258 ResultBuilder& setRhs(std::string const& rhs);
1259 ResultBuilder& setOp(std::string const& op);
1260
1261 void endExpression();
1262
1263 std::string reconstructExpression() const;
1264 AssertionResult build() const;
1265
1266 void useActiveException(ResultDisposition::Flags resultDisposition = ResultDisposition::Normal);
1267 void captureResult(ResultWas::OfType resultType);
1268 void captureExpression();
1269 void captureExpectedException(std::string const& expectedMessage);
1270 void captureExpectedException(Matchers::Impl::Matcher<std::string> const& matcher);
1271 void handleResult(AssertionResult const& result);
1272 void react();
1273 bool shouldDebugBreak() const;
1274 bool allowThrows() const;
1275
1276 private:
1277 AssertionInfo m_assertionInfo;
1278 AssertionResultData m_data;
1279 struct ExprComponents {
ExprComponentsCatch::ResultBuilder::ExprComponents1280 ExprComponents() : testFalse(false) {}
1281 bool testFalse;
1282 std::string lhs, rhs, op;
1283 } m_exprComponents;
1284 CopyableStream m_stream;
1285
1286 bool m_shouldDebugBreak;
1287 bool m_shouldThrow;
1288 };
1289
1290 } // namespace Catch
1291
1292 // Include after due to circular dependency:
1293 // #included from: catch_expression_lhs.hpp
1294 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1295
1296 // #included from: catch_evaluate.hpp
1297 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
1298
1299 #ifdef _MSC_VER
1300 #pragma warning(push)
1301 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
1302 #endif
1303
1304 #include <cstddef>
1305
1306 namespace Catch {
1307 namespace Internal {
1308
1309 enum Operator {
1310 IsEqualTo,
1311 IsNotEqualTo,
1312 IsLessThan,
1313 IsGreaterThan,
1314 IsLessThanOrEqualTo,
1315 IsGreaterThanOrEqualTo
1316 };
1317
getNameCatch::Internal::OperatorTraits1318 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
getNameCatch::Internal::OperatorTraits1319 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
getNameCatch::Internal::OperatorTraits1320 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
getNameCatch::Internal::OperatorTraits1321 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
getNameCatch::Internal::OperatorTraits1322 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
getNameCatch::Internal::OperatorTraits1323 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
getNameCatch::Internal::OperatorTraits1324 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
1325
1326 template<typename T>
opCast(T const & t)1327 inline T& opCast(T const& t) { return const_cast<T&>(t); }
1328
1329 // nullptr_t support based on pull request #154 from Konstantin Baumann
1330 #ifdef CATCH_CONFIG_CPP11_NULLPTR
opCast(std::nullptr_t)1331 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1332 #endif // CATCH_CONFIG_CPP11_NULLPTR
1333
1334 // So the compare overloads can be operator agnostic we convey the operator as a template
1335 // enum, which is used to specialise an Evaluator for doing the comparison.
1336 template<typename T1, typename T2, Operator Op>
1337 class Evaluator{};
1338
1339 template<typename T1, typename T2>
1340 struct Evaluator<T1, T2, IsEqualTo> {
evaluateCatch::Internal::Evaluator1341 static bool evaluate(T1 const& lhs, T2 const& rhs) {
1342 return bool(opCast(lhs) == opCast(rhs));
1343 }
1344 };
1345 template<typename T1, typename T2>
1346 struct Evaluator<T1, T2, IsNotEqualTo> {
evaluateCatch::Internal::Evaluator1347 static bool evaluate(T1 const& lhs, T2 const& rhs) {
1348 return bool(opCast(lhs) != opCast(rhs));
1349 }
1350 };
1351 template<typename T1, typename T2>
1352 struct Evaluator<T1, T2, IsLessThan> {
evaluateCatch::Internal::Evaluator1353 static bool evaluate(T1 const& lhs, T2 const& rhs) {
1354 return bool(opCast(lhs) < opCast(rhs));
1355 }
1356 };
1357 template<typename T1, typename T2>
1358 struct Evaluator<T1, T2, IsGreaterThan> {
evaluateCatch::Internal::Evaluator1359 static bool evaluate(T1 const& lhs, T2 const& rhs) {
1360 return bool(opCast(lhs) > opCast(rhs));
1361 }
1362 };
1363 template<typename T1, typename T2>
1364 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
evaluateCatch::Internal::Evaluator1365 static bool evaluate(T1 const& lhs, T2 const& rhs) {
1366 return bool(opCast(lhs) >= opCast(rhs));
1367 }
1368 };
1369 template<typename T1, typename T2>
1370 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
evaluateCatch::Internal::Evaluator1371 static bool evaluate(T1 const& lhs, T2 const& rhs) {
1372 return bool(opCast(lhs) <= opCast(rhs));
1373 }
1374 };
1375
1376 template<Operator Op, typename T1, typename T2>
applyEvaluator(T1 const & lhs,T2 const & rhs)1377 bool applyEvaluator(T1 const& lhs, T2 const& rhs) {
1378 return Evaluator<T1, T2, Op>::evaluate(lhs, rhs);
1379 }
1380
1381 // This level of indirection allows us to specialise for integer types
1382 // to avoid signed/ unsigned warnings
1383
1384 // "base" overload
1385 template<Operator Op, typename T1, typename T2>
compare(T1 const & lhs,T2 const & rhs)1386 bool compare(T1 const& lhs, T2 const& rhs) {
1387 return Evaluator<T1, T2, Op>::evaluate(lhs, rhs);
1388 }
1389
1390 // unsigned X to int
compare(unsigned int lhs,int rhs)1391 template<Operator Op> bool compare(unsigned int lhs, int rhs) {
1392 return applyEvaluator<Op>(lhs, static_cast<unsigned int>(rhs));
1393 }
compare(unsigned long lhs,int rhs)1394 template<Operator Op> bool compare(unsigned long lhs, int rhs) {
1395 return applyEvaluator<Op>(lhs, static_cast<unsigned int>(rhs));
1396 }
compare(unsigned char lhs,int rhs)1397 template<Operator Op> bool compare(unsigned char lhs, int rhs) {
1398 return applyEvaluator<Op>(lhs, static_cast<unsigned int>(rhs));
1399 }
1400
1401 // unsigned X to long
compare(unsigned int lhs,long rhs)1402 template<Operator Op> bool compare(unsigned int lhs, long rhs) {
1403 return applyEvaluator<Op>(lhs, static_cast<unsigned long>(rhs));
1404 }
compare(unsigned long lhs,long rhs)1405 template<Operator Op> bool compare(unsigned long lhs, long rhs) {
1406 return applyEvaluator<Op>(lhs, static_cast<unsigned long>(rhs));
1407 }
compare(unsigned char lhs,long rhs)1408 template<Operator Op> bool compare(unsigned char lhs, long rhs) {
1409 return applyEvaluator<Op>(lhs, static_cast<unsigned long>(rhs));
1410 }
1411
1412 // int to unsigned X
compare(int lhs,unsigned int rhs)1413 template<Operator Op> bool compare(int lhs, unsigned int rhs) {
1414 return applyEvaluator<Op>(static_cast<unsigned int>(lhs), rhs);
1415 }
compare(int lhs,unsigned long rhs)1416 template<Operator Op> bool compare(int lhs, unsigned long rhs) {
1417 return applyEvaluator<Op>(static_cast<unsigned int>(lhs), rhs);
1418 }
compare(int lhs,unsigned char rhs)1419 template<Operator Op> bool compare(int lhs, unsigned char rhs) {
1420 return applyEvaluator<Op>(static_cast<unsigned int>(lhs), rhs);
1421 }
1422
1423 // long to unsigned X
compare(long lhs,unsigned int rhs)1424 template<Operator Op> bool compare(long lhs, unsigned int rhs) {
1425 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1426 }
compare(long lhs,unsigned long rhs)1427 template<Operator Op> bool compare(long lhs, unsigned long rhs) {
1428 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1429 }
compare(long lhs,unsigned char rhs)1430 template<Operator Op> bool compare(long lhs, unsigned char rhs) {
1431 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1432 }
1433
1434 // pointer to long (when comparing against NULL)
compare(long lhs,T * rhs)1435 template<Operator Op, typename T> bool compare(long lhs, T* rhs) {
1436 return Evaluator<T*, T*, Op>::evaluate(reinterpret_cast<T*>(lhs), rhs);
1437 }
compare(T * lhs,long rhs)1438 template<Operator Op, typename T> bool compare(T* lhs, long rhs) {
1439 return Evaluator<T*, T*, Op>::evaluate(lhs, reinterpret_cast<T*>(rhs));
1440 }
1441
1442 // pointer to int (when comparing against NULL)
compare(int lhs,T * rhs)1443 template<Operator Op, typename T> bool compare(int lhs, T* rhs) {
1444 return Evaluator<T*, T*, Op>::evaluate(reinterpret_cast<T*>(lhs), rhs);
1445 }
compare(T * lhs,int rhs)1446 template<Operator Op, typename T> bool compare(T* lhs, int rhs) {
1447 return Evaluator<T*, T*, Op>::evaluate(lhs, reinterpret_cast<T*>(rhs));
1448 }
1449
1450 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1451 // long long to unsigned X
compare(long long lhs,unsigned int rhs)1452 template<Operator Op> bool compare(long long lhs, unsigned int rhs) {
1453 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1454 }
compare(long long lhs,unsigned long rhs)1455 template<Operator Op> bool compare(long long lhs, unsigned long rhs) {
1456 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1457 }
compare(long long lhs,unsigned long long rhs)1458 template<Operator Op> bool compare(long long lhs, unsigned long long rhs) {
1459 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1460 }
compare(long long lhs,unsigned char rhs)1461 template<Operator Op> bool compare(long long lhs, unsigned char rhs) {
1462 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1463 }
1464
1465 // unsigned long long to X
compare(unsigned long long lhs,int rhs)1466 template<Operator Op> bool compare(unsigned long long lhs, int rhs) {
1467 return applyEvaluator<Op>(static_cast<long>(lhs), rhs);
1468 }
compare(unsigned long long lhs,long rhs)1469 template<Operator Op> bool compare(unsigned long long lhs, long rhs) {
1470 return applyEvaluator<Op>(static_cast<long>(lhs), rhs);
1471 }
compare(unsigned long long lhs,long long rhs)1472 template<Operator Op> bool compare(unsigned long long lhs, long long rhs) {
1473 return applyEvaluator<Op>(static_cast<long>(lhs), rhs);
1474 }
compare(unsigned long long lhs,char rhs)1475 template<Operator Op> bool compare(unsigned long long lhs, char rhs) {
1476 return applyEvaluator<Op>(static_cast<long>(lhs), rhs);
1477 }
1478
1479 // pointer to long long (when comparing against NULL)
compare(long long lhs,T * rhs)1480 template<Operator Op, typename T> bool compare(long long lhs, T* rhs) {
1481 return Evaluator<T*, T*, Op>::evaluate(reinterpret_cast<T*>(lhs), rhs);
1482 }
compare(T * lhs,long long rhs)1483 template<Operator Op, typename T> bool compare(T* lhs, long long rhs) {
1484 return Evaluator<T*, T*, Op>::evaluate(lhs, reinterpret_cast<T*>(rhs));
1485 }
1486 #endif // CATCH_CONFIG_CPP11_LONG_LONG
1487
1488 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1489 // pointer to nullptr_t (when comparing against nullptr)
compare(std::nullptr_t,T * rhs)1490 template<Operator Op, typename T> bool compare(std::nullptr_t, T* rhs) {
1491 return Evaluator<T*, T*, Op>::evaluate(nullptr, rhs);
1492 }
compare(T * lhs,std::nullptr_t)1493 template<Operator Op, typename T> bool compare(T* lhs, std::nullptr_t) {
1494 return Evaluator<T*, T*, Op>::evaluate(lhs, nullptr);
1495 }
1496 #endif // CATCH_CONFIG_CPP11_NULLPTR
1497
1498 } // end of namespace Internal
1499 } // end of namespace Catch
1500
1501 #ifdef _MSC_VER
1502 #pragma warning(pop)
1503 #endif
1504
1505 // #included from: catch_tostring.h
1506 #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1507
1508 #include <sstream>
1509 #include <iomanip>
1510 #include <limits>
1511 #include <vector>
1512 #include <cstddef>
1513
1514 #ifdef __OBJC__
1515 // #included from: catch_objc_arc.hpp
1516 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1517
1518 #import <Foundation/Foundation.h>
1519
1520 #ifdef __has_feature
1521 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
1522 #else
1523 #define CATCH_ARC_ENABLED 0
1524 #endif
1525
1526 void arcSafeRelease(NSObject* obj);
1527 id performOptionalSelector(id obj, SEL sel);
1528
1529 #if !CATCH_ARC_ENABLED
arcSafeRelease(NSObject * obj)1530 inline void arcSafeRelease(NSObject* obj) {
1531 [obj release];
1532 }
performOptionalSelector(id obj,SEL sel)1533 inline id performOptionalSelector(id obj, SEL sel) {
1534 if ([obj respondsToSelector : sel])
1535 return[obj performSelector : sel];
1536 return nil;
1537 }
1538 #define CATCH_UNSAFE_UNRETAINED
1539 #define CATCH_ARC_STRONG
1540 #else
arcSafeRelease(NSObject *)1541 inline void arcSafeRelease(NSObject*){}
performOptionalSelector(id obj,SEL sel)1542 inline id performOptionalSelector(id obj, SEL sel) {
1543 #ifdef __clang__
1544 #pragma clang diagnostic push
1545 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1546 #endif
1547 if ([obj respondsToSelector : sel])
1548 return[obj performSelector : sel];
1549 #ifdef __clang__
1550 #pragma clang diagnostic pop
1551 #endif
1552 return nil;
1553 }
1554 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1555 #define CATCH_ARC_STRONG __strong
1556 #endif
1557
1558 #endif
1559
1560 #ifdef CATCH_CONFIG_CPP11_TUPLE
1561 #include <tuple>
1562 #endif
1563
1564 #ifdef CATCH_CONFIG_CPP11_IS_ENUM
1565 #include <type_traits>
1566 #endif
1567
1568 namespace Catch {
1569
1570 // Why we're here.
1571 template<typename T>
1572 std::string toString(T const& value);
1573
1574 // Built in overloads
1575
1576 std::string toString(std::string const& value);
1577 std::string toString(std::wstring const& value);
1578 std::string toString(const char* const value);
1579 std::string toString(char* const value);
1580 std::string toString(const wchar_t* const value);
1581 std::string toString(wchar_t* const value);
1582 std::string toString(int value);
1583 std::string toString(unsigned long value);
1584 std::string toString(unsigned int value);
1585 std::string toString(const double value);
1586 std::string toString(const float value);
1587 std::string toString(bool value);
1588 std::string toString(char value);
1589 std::string toString(signed char value);
1590 std::string toString(unsigned char value);
1591
1592 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1593 std::string toString(long long value);
1594 std::string toString(unsigned long long value);
1595 #endif
1596
1597 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1598 std::string toString(std::nullptr_t);
1599 #endif
1600
1601 #ifdef __OBJC__
1602 std::string toString(NSString const * const& nsstring);
1603 std::string toString(NSString * CATCH_ARC_STRONG const& nsstring);
1604 std::string toString(NSObject* const& nsObject);
1605 #endif
1606
1607 namespace Detail {
1608
1609 extern const std::string unprintableString;
1610
1611 struct BorgType {
1612 template<typename T> BorgType(T const&);
1613 };
1614
1615 struct TrueType { char sizer[1]; };
1616 struct FalseType { char sizer[2]; };
1617
1618 TrueType& testStreamable(std::ostream&);
1619 FalseType testStreamable(FalseType);
1620
1621 FalseType operator<<(std::ostream const&, BorgType const&);
1622
1623 template<typename T>
1624 struct IsStreamInsertable {
1625 static std::ostream &s;
1626 static T const&t;
1627 enum { value = sizeof(testStreamable(s << t)) == sizeof(TrueType) };
1628 };
1629
1630 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1631 template<typename T,
1632 bool IsEnum = std::is_enum<T>::value
1633 >
1634 struct EnumStringMaker
1635 {
convertCatch::Detail::EnumStringMaker1636 static std::string convert(T const&) { return unprintableString; }
1637 };
1638
1639 template<typename T>
1640 struct EnumStringMaker<T, true>
1641 {
convertCatch::Detail::EnumStringMaker1642 static std::string convert(T const& v)
1643 {
1644 return ::Catch::toString(
1645 static_cast<typename std::underlying_type<T>::type>(v)
1646 );
1647 }
1648 };
1649 #endif
1650 template<bool C>
1651 struct StringMakerBase {
1652 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1653 template<typename T>
convertCatch::Detail::StringMakerBase1654 static std::string convert(T const& v)
1655 {
1656 return EnumStringMaker<T>::convert(v);
1657 }
1658 #else
1659 template<typename T>
1660 static std::string convert(T const&) { return unprintableString; }
1661 #endif
1662 };
1663
1664 template<>
1665 struct StringMakerBase<true> {
1666 template<typename T>
convertCatch::Detail::StringMakerBase1667 static std::string convert(T const& _value) {
1668 std::ostringstream oss;
1669 oss << _value;
1670 return oss.str();
1671 }
1672 };
1673
1674 std::string rawMemoryToString(const void *object, std::size_t size);
1675
1676 template<typename T>
rawMemoryToString(const T & object)1677 inline std::string rawMemoryToString(const T& object) {
1678 return rawMemoryToString(&object, sizeof(object));
1679 }
1680
1681 } // end namespace Detail
1682
1683 template<typename T>
1684 struct StringMaker :
1685 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
1686
1687 template<typename T>
1688 struct StringMaker<T*> {
1689 template<typename U>
convertCatch::StringMaker1690 static std::string convert(U* p) {
1691 if (!p)
1692 return "NULL";
1693 else
1694 return Detail::rawMemoryToString(p);
1695 }
1696 };
1697
1698 template<typename R, typename C>
1699 struct StringMaker<R C::*> {
convertCatch::StringMaker1700 static std::string convert(R C::* p) {
1701 if (!p)
1702 return "NULL";
1703 else
1704 return Detail::rawMemoryToString(p);
1705 }
1706 };
1707
1708 namespace Detail {
1709 template<typename InputIterator>
1710 std::string rangeToString(InputIterator first, InputIterator last);
1711 }
1712
1713 //template<typename T, typename Allocator>
1714 //struct StringMaker<std::vector<T, Allocator> > {
1715 // static std::string convert( std::vector<T,Allocator> const& v ) {
1716 // return Detail::rangeToString( v.begin(), v.end() );
1717 // }
1718 //};
1719
1720 template<typename T, typename Allocator>
toString(std::vector<T,Allocator> const & v)1721 std::string toString(std::vector<T, Allocator> const& v) {
1722 return Detail::rangeToString(v.begin(), v.end());
1723 }
1724
1725 #ifdef CATCH_CONFIG_CPP11_TUPLE
1726
1727 // toString for tuples
1728 namespace TupleDetail {
1729 template<
1730 typename Tuple,
1731 std::size_t N = 0,
1732 bool = (N < std::tuple_size<Tuple>::value)
1733 >
1734 struct ElementPrinter {
printCatch::TupleDetail::ElementPrinter1735 static void print(const Tuple& tuple, std::ostream& os)
1736 {
1737 os << (N ? ", " : " ")
1738 << Catch::toString(std::get<N>(tuple));
1739 ElementPrinter<Tuple, N + 1>::print(tuple, os);
1740 }
1741 };
1742
1743 template<
1744 typename Tuple,
1745 std::size_t N
1746 >
1747 struct ElementPrinter<Tuple, N, false> {
printCatch::TupleDetail::ElementPrinter1748 static void print(const Tuple&, std::ostream&) {}
1749 };
1750
1751 }
1752
1753 template<typename ...Types>
1754 struct StringMaker<std::tuple<Types...>> {
1755
convertCatch::StringMaker1756 static std::string convert(const std::tuple<Types...>& tuple)
1757 {
1758 std::ostringstream os;
1759 os << '{';
1760 TupleDetail::ElementPrinter<std::tuple<Types...>>::print(tuple, os);
1761 os << " }";
1762 return os.str();
1763 }
1764 };
1765 #endif // CATCH_CONFIG_CPP11_TUPLE
1766
1767 namespace Detail {
1768 template<typename T>
makeString(T const & value)1769 std::string makeString(T const& value) {
1770 return StringMaker<T>::convert(value);
1771 }
1772 } // end namespace Detail
1773
1774 /// \brief converts any type to a string
1775 ///
1776 /// The default template forwards on to ostringstream - except when an
1777 /// ostringstream overload does not exist - in which case it attempts to detect
1778 /// that and writes {?}.
1779 /// Overload (not specialise) this template for custom typs that you don't want
1780 /// to provide an ostream overload for.
1781 template<typename T>
toString(T const & value)1782 std::string toString(T const& value) {
1783 return StringMaker<T>::convert(value);
1784 }
1785
1786 namespace Detail {
1787 template<typename InputIterator>
rangeToString(InputIterator first,InputIterator last)1788 std::string rangeToString(InputIterator first, InputIterator last) {
1789 std::ostringstream oss;
1790 oss << "{ ";
1791 if (first != last) {
1792 oss << Catch::toString(*first);
1793 for (++first; first != last; ++first)
1794 oss << ", " << Catch::toString(*first);
1795 }
1796 oss << " }";
1797 return oss.str();
1798 }
1799 }
1800
1801 } // end namespace Catch
1802
1803 namespace Catch {
1804
1805 // Wraps the LHS of an expression and captures the operator and RHS (if any) -
1806 // wrapping them all in a ResultBuilder object
1807 template<typename T>
1808 class ExpressionLhs {
1809 ExpressionLhs& operator = (ExpressionLhs const&);
1810 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1811 ExpressionLhs& operator = (ExpressionLhs &&) = delete;
1812 # endif
1813
1814 public:
ExpressionLhs(ResultBuilder & rb,T lhs)1815 ExpressionLhs(ResultBuilder& rb, T lhs) : m_rb(rb), m_lhs(lhs) {}
1816 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1817 ExpressionLhs(ExpressionLhs const&) = default;
1818 ExpressionLhs(ExpressionLhs &&) = default;
1819 # endif
1820
1821 template<typename RhsT>
operator ==(RhsT const & rhs)1822 ResultBuilder& operator == (RhsT const& rhs) {
1823 return captureExpression<Internal::IsEqualTo>(rhs);
1824 }
1825
1826 template<typename RhsT>
operator !=(RhsT const & rhs)1827 ResultBuilder& operator != (RhsT const& rhs) {
1828 return captureExpression<Internal::IsNotEqualTo>(rhs);
1829 }
1830
1831 template<typename RhsT>
operator <(RhsT const & rhs)1832 ResultBuilder& operator < (RhsT const& rhs) {
1833 return captureExpression<Internal::IsLessThan>(rhs);
1834 }
1835
1836 template<typename RhsT>
operator >(RhsT const & rhs)1837 ResultBuilder& operator > (RhsT const& rhs) {
1838 return captureExpression<Internal::IsGreaterThan>(rhs);
1839 }
1840
1841 template<typename RhsT>
operator <=(RhsT const & rhs)1842 ResultBuilder& operator <= (RhsT const& rhs) {
1843 return captureExpression<Internal::IsLessThanOrEqualTo>(rhs);
1844 }
1845
1846 template<typename RhsT>
operator >=(RhsT const & rhs)1847 ResultBuilder& operator >= (RhsT const& rhs) {
1848 return captureExpression<Internal::IsGreaterThanOrEqualTo>(rhs);
1849 }
1850
operator ==(bool rhs)1851 ResultBuilder& operator == (bool rhs) {
1852 return captureExpression<Internal::IsEqualTo>(rhs);
1853 }
1854
operator !=(bool rhs)1855 ResultBuilder& operator != (bool rhs) {
1856 return captureExpression<Internal::IsNotEqualTo>(rhs);
1857 }
1858
endExpression()1859 void endExpression() {
1860 bool value = m_lhs ? true : false;
1861 m_rb
1862 .setLhs(Catch::toString(value))
1863 .setResultType(value)
1864 .endExpression();
1865 }
1866
1867 // Only simple binary expressions are allowed on the LHS.
1868 // If more complex compositions are required then place the sub expression in parentheses
1869 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + (RhsT const&);
1870 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - (RhsT const&);
1871 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / (RhsT const&);
1872 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * (RhsT const&);
1873 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && (RhsT const&);
1874 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || (RhsT const&);
1875
1876 private:
1877 template<Internal::Operator Op, typename RhsT>
captureExpression(RhsT const & rhs)1878 ResultBuilder& captureExpression(RhsT const& rhs) {
1879 return m_rb
1880 .setResultType(Internal::compare<Op>(m_lhs, rhs))
1881 .setLhs(Catch::toString(m_lhs))
1882 .setRhs(Catch::toString(rhs))
1883 .setOp(Internal::OperatorTraits<Op>::getName());
1884 }
1885
1886 private:
1887 ResultBuilder& m_rb;
1888 T m_lhs;
1889 };
1890
1891 } // end namespace Catch
1892
1893
1894 namespace Catch {
1895
1896 template<typename T>
operator <=(T const & operand)1897 inline ExpressionLhs<T const&> ResultBuilder::operator <= (T const& operand) {
1898 return ExpressionLhs<T const&>(*this, operand);
1899 }
1900
operator <=(bool value)1901 inline ExpressionLhs<bool> ResultBuilder::operator <= (bool value) {
1902 return ExpressionLhs<bool>(*this, value);
1903 }
1904
1905 } // namespace Catch
1906
1907 // #included from: catch_message.h
1908 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1909
1910 #include <string>
1911
1912 namespace Catch {
1913
1914 struct MessageInfo {
1915 MessageInfo(std::string const& _macroName,
1916 SourceLineInfo const& _lineInfo,
1917 ResultWas::OfType _type);
1918
1919 std::string macroName;
1920 SourceLineInfo lineInfo;
1921 ResultWas::OfType type;
1922 std::string message;
1923 unsigned int sequence;
1924
operator ==Catch::MessageInfo1925 bool operator == (MessageInfo const& other) const {
1926 return sequence == other.sequence;
1927 }
operator <Catch::MessageInfo1928 bool operator < (MessageInfo const& other) const {
1929 return sequence < other.sequence;
1930 }
1931 private:
1932 static unsigned int globalCount;
1933 };
1934
1935 struct MessageBuilder {
MessageBuilderCatch::MessageBuilder1936 MessageBuilder(std::string const& macroName,
1937 SourceLineInfo const& lineInfo,
1938 ResultWas::OfType type)
1939 : m_info(macroName, lineInfo, type)
1940 {}
1941
1942 template<typename T>
operator <<Catch::MessageBuilder1943 MessageBuilder& operator << (T const& value) {
1944 m_stream << value;
1945 return *this;
1946 }
1947
1948 MessageInfo m_info;
1949 std::ostringstream m_stream;
1950 };
1951
1952 class ScopedMessage {
1953 public:
1954 ScopedMessage(MessageBuilder const& builder);
1955 ScopedMessage(ScopedMessage const& other);
1956 ~ScopedMessage();
1957
1958 MessageInfo m_info;
1959 };
1960
1961 } // end namespace Catch
1962
1963 // #included from: catch_interfaces_capture.h
1964 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
1965
1966 #include <string>
1967
1968 namespace Catch {
1969
1970 class TestCase;
1971 class AssertionResult;
1972 struct AssertionInfo;
1973 struct SectionInfo;
1974 struct SectionEndInfo;
1975 struct MessageInfo;
1976 class ScopedMessageBuilder;
1977 struct Counts;
1978
1979 struct IResultCapture {
1980
1981 virtual ~IResultCapture();
1982
1983 virtual void assertionEnded(AssertionResult const& result) = 0;
1984 virtual bool sectionStarted(SectionInfo const& sectionInfo,
1985 Counts& assertions) = 0;
1986 virtual void sectionEnded(SectionEndInfo const& endInfo) = 0;
1987 virtual void sectionEndedEarly(SectionEndInfo const& endInfo) = 0;
1988 virtual void pushScopedMessage(MessageInfo const& message) = 0;
1989 virtual void popScopedMessage(MessageInfo const& message) = 0;
1990
1991 virtual std::string getCurrentTestName() const = 0;
1992 virtual const AssertionResult* getLastResult() const = 0;
1993
1994 virtual void handleFatalErrorCondition(std::string const& message) = 0;
1995 };
1996
1997 IResultCapture& getResultCapture();
1998 }
1999
2000 // #included from: catch_debugger.h
2001 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
2002
2003 // #included from: catch_platform.h
2004 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
2005
2006 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
2007 #define CATCH_PLATFORM_MAC
2008 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
2009 #define CATCH_PLATFORM_IPHONE
2010 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
2011 #define CATCH_PLATFORM_WINDOWS
2012 #endif
2013
2014 #include <string>
2015
2016 namespace Catch{
2017
2018 bool isDebuggerActive();
2019 void writeToDebugConsole(std::string const& text);
2020 }
2021
2022 #ifdef CATCH_PLATFORM_MAC
2023
2024 // The following code snippet based on:
2025 // http://cocoawithlove.com/2008/03/break-into-debugger.html
2026 #ifdef DEBUG
2027 #if defined(__ppc64__) || defined(__ppc__)
2028 #define CATCH_BREAK_INTO_DEBUGGER() \
2029 if( Catch::isDebuggerActive() ) { \
2030 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
2031 : : : "memory","r0","r3","r4" ); \
2032 }
2033 #else
2034 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
2035 #endif
2036 #endif
2037
2038 #elif defined(_MSC_VER)
2039 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
2040 #elif defined(__MINGW32__)
2041 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
2042 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
2043 #endif
2044
2045 #ifndef CATCH_BREAK_INTO_DEBUGGER
2046 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
2047 #endif
2048
2049 // #included from: catch_interfaces_runner.h
2050 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2051
2052 namespace Catch {
2053 class TestCase;
2054
2055 struct IRunner {
2056 virtual ~IRunner();
2057 virtual bool aborting() const = 0;
2058 };
2059 }
2060
2061 ///////////////////////////////////////////////////////////////////////////////
2062 // In the event of a failure works out if the debugger needs to be invoked
2063 // and/or an exception thrown and takes appropriate action.
2064 // This needs to be done as a macro so the debugger will stop in the user
2065 // source code rather than in Catch library code
2066 #define INTERNAL_CATCH_REACT( resultBuilder ) \
2067 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2068 resultBuilder.react();
2069
2070 ///////////////////////////////////////////////////////////////////////////////
2071 #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
2072 do { \
2073 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2074 try { \
2075 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2076 ( __catchResult <= expr ).endExpression(); \
2077 } \
2078 catch( ... ) { \
2079 __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
2080 } \
2081 INTERNAL_CATCH_REACT( __catchResult ) \
2082 } while( Catch::isTrue( false && !!(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
2083
2084 ///////////////////////////////////////////////////////////////////////////////
2085 #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
2086 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2087 if( Catch::getResultCapture().getLastResult()->succeeded() )
2088
2089 ///////////////////////////////////////////////////////////////////////////////
2090 #define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
2091 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2092 if( !Catch::getResultCapture().getLastResult()->succeeded() )
2093
2094 ///////////////////////////////////////////////////////////////////////////////
2095 #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
2096 do { \
2097 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2098 try { \
2099 expr; \
2100 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2101 } \
2102 catch( ... ) { \
2103 __catchResult.useActiveException( resultDisposition ); \
2104 } \
2105 INTERNAL_CATCH_REACT( __catchResult ) \
2106 } while( Catch::alwaysFalse() )
2107
2108 ///////////////////////////////////////////////////////////////////////////////
2109 #define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
2110 do { \
2111 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
2112 if( __catchResult.allowThrows() ) \
2113 try { \
2114 expr; \
2115 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2116 } \
2117 catch( ... ) { \
2118 __catchResult.captureExpectedException( matcher ); \
2119 } \
2120 else \
2121 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2122 INTERNAL_CATCH_REACT( __catchResult ) \
2123 } while( Catch::alwaysFalse() )
2124
2125 ///////////////////////////////////////////////////////////////////////////////
2126 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
2127 do { \
2128 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2129 if( __catchResult.allowThrows() ) \
2130 try { \
2131 expr; \
2132 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2133 } \
2134 catch( exceptionType ) { \
2135 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2136 } \
2137 catch( ... ) { \
2138 __catchResult.useActiveException( resultDisposition ); \
2139 } \
2140 else \
2141 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2142 INTERNAL_CATCH_REACT( __catchResult ) \
2143 } while( Catch::alwaysFalse() )
2144
2145 ///////////////////////////////////////////////////////////////////////////////
2146 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2147 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
2148 do { \
2149 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2150 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2151 __catchResult.captureResult( messageType ); \
2152 INTERNAL_CATCH_REACT( __catchResult ) \
2153 } while( Catch::alwaysFalse() )
2154 #else
2155 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
2156 do { \
2157 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2158 __catchResult << log + ::Catch::StreamEndStop(); \
2159 __catchResult.captureResult( messageType ); \
2160 INTERNAL_CATCH_REACT( __catchResult ) \
2161 } while( Catch::alwaysFalse() )
2162 #endif
2163
2164 ///////////////////////////////////////////////////////////////////////////////
2165 #define INTERNAL_CATCH_INFO( log, macroName ) \
2166 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
2167
2168 ///////////////////////////////////////////////////////////////////////////////
2169 #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
2170 do { \
2171 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
2172 try { \
2173 std::string matcherAsString = (matcher).toString(); \
2174 __catchResult \
2175 .setLhs( Catch::toString( arg ) ) \
2176 .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
2177 .setOp( "matches" ) \
2178 .setResultType( (matcher).match( arg ) ); \
2179 __catchResult.captureExpression(); \
2180 } catch( ... ) { \
2181 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
2182 } \
2183 INTERNAL_CATCH_REACT( __catchResult ) \
2184 } while( Catch::alwaysFalse() )
2185
2186 // #included from: internal/catch_section.h
2187 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2188
2189 // #included from: catch_section_info.h
2190 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2191
2192 // #included from: catch_totals.hpp
2193 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2194
2195 #include <cstddef>
2196
2197 namespace Catch {
2198
2199 struct Counts {
CountsCatch::Counts2200 Counts() : passed(0), failed(0), failedButOk(0) {}
2201
operator -Catch::Counts2202 Counts operator - (Counts const& other) const {
2203 Counts diff;
2204 diff.passed = passed - other.passed;
2205 diff.failed = failed - other.failed;
2206 diff.failedButOk = failedButOk - other.failedButOk;
2207 return diff;
2208 }
operator +=Catch::Counts2209 Counts& operator += (Counts const& other) {
2210 passed += other.passed;
2211 failed += other.failed;
2212 failedButOk += other.failedButOk;
2213 return *this;
2214 }
2215
totalCatch::Counts2216 std::size_t total() const {
2217 return passed + failed + failedButOk;
2218 }
allPassedCatch::Counts2219 bool allPassed() const {
2220 return failed == 0 && failedButOk == 0;
2221 }
allOkCatch::Counts2222 bool allOk() const {
2223 return failed == 0;
2224 }
2225
2226 std::size_t passed;
2227 std::size_t failed;
2228 std::size_t failedButOk;
2229 };
2230
2231 struct Totals {
2232
operator -Catch::Totals2233 Totals operator - (Totals const& other) const {
2234 Totals diff;
2235 diff.assertions = assertions - other.assertions;
2236 diff.testCases = testCases - other.testCases;
2237 return diff;
2238 }
2239
deltaCatch::Totals2240 Totals delta(Totals const& prevTotals) const {
2241 Totals diff = *this - prevTotals;
2242 if (diff.assertions.failed > 0)
2243 ++diff.testCases.failed;
2244 else if (diff.assertions.failedButOk > 0)
2245 ++diff.testCases.failedButOk;
2246 else
2247 ++diff.testCases.passed;
2248 return diff;
2249 }
2250
operator +=Catch::Totals2251 Totals& operator += (Totals const& other) {
2252 assertions += other.assertions;
2253 testCases += other.testCases;
2254 return *this;
2255 }
2256
2257 Counts assertions;
2258 Counts testCases;
2259 };
2260 }
2261
2262 namespace Catch {
2263
2264 struct SectionInfo {
2265 SectionInfo
2266 (SourceLineInfo const& _lineInfo,
2267 std::string const& _name,
2268 std::string const& _description = std::string());
2269
2270 std::string name;
2271 std::string description;
2272 SourceLineInfo lineInfo;
2273 };
2274
2275 struct SectionEndInfo {
SectionEndInfoCatch::SectionEndInfo2276 SectionEndInfo(SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds)
2277 : sectionInfo(_sectionInfo), prevAssertions(_prevAssertions), durationInSeconds(_durationInSeconds)
2278 {}
2279
2280 SectionInfo sectionInfo;
2281 Counts prevAssertions;
2282 double durationInSeconds;
2283 };
2284
2285 } // end namespace Catch
2286
2287 // #included from: catch_timer.h
2288 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2289
2290 #ifdef CATCH_PLATFORM_WINDOWS
2291 typedef unsigned long long uint64_t;
2292 #else
2293 #include <stdint.h>
2294 #endif
2295
2296 namespace Catch {
2297
2298 class Timer {
2299 public:
Timer()2300 Timer() : m_ticks(0) {}
2301 void start();
2302 unsigned int getElapsedMicroseconds() const;
2303 unsigned int getElapsedMilliseconds() const;
2304 double getElapsedSeconds() const;
2305
2306 private:
2307 uint64_t m_ticks;
2308 };
2309
2310 } // namespace Catch
2311
2312 #include <string>
2313
2314 namespace Catch {
2315
2316 class Section : NonCopyable {
2317 public:
2318 Section(SectionInfo const& info);
2319 ~Section();
2320
2321 // This indicates whether the section should be executed or not
2322 operator bool() const;
2323
2324 private:
2325 SectionInfo m_info;
2326
2327 std::string m_name;
2328 Counts m_assertions;
2329 bool m_sectionIncluded;
2330 Timer m_timer;
2331 };
2332
2333 } // end namespace Catch
2334
2335 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2336 #define INTERNAL_CATCH_SECTION( ... ) \
2337 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
2338 #else
2339 #define INTERNAL_CATCH_SECTION( name, desc ) \
2340 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
2341 #endif
2342
2343 // #included from: internal/catch_generators.hpp
2344 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2345
2346 #include <iterator>
2347 #include <vector>
2348 #include <string>
2349 #include <stdlib.h>
2350
2351 namespace Catch {
2352
2353 template<typename T>
2354 struct IGenerator {
~IGeneratorCatch::IGenerator2355 virtual ~IGenerator() {}
2356 virtual T getValue(std::size_t index) const = 0;
2357 virtual std::size_t size() const = 0;
2358 };
2359
2360 template<typename T>
2361 class BetweenGenerator : public IGenerator<T> {
2362 public:
BetweenGenerator(T from,T to)2363 BetweenGenerator(T from, T to) : m_from(from), m_to(to){}
2364
getValue(std::size_t index) const2365 virtual T getValue(std::size_t index) const {
2366 return m_from + static_cast<int>(index);
2367 }
2368
size() const2369 virtual std::size_t size() const {
2370 return static_cast<std::size_t>(1 + m_to - m_from);
2371 }
2372
2373 private:
2374
2375 T m_from;
2376 T m_to;
2377 };
2378
2379 template<typename T>
2380 class ValuesGenerator : public IGenerator<T> {
2381 public:
ValuesGenerator()2382 ValuesGenerator(){}
2383
add(T value)2384 void add(T value) {
2385 m_values.push_back(value);
2386 }
2387
getValue(std::size_t index) const2388 virtual T getValue(std::size_t index) const {
2389 return m_values[index];
2390 }
2391
size() const2392 virtual std::size_t size() const {
2393 return m_values.size();
2394 }
2395
2396 private:
2397 std::vector<T> m_values;
2398 };
2399
2400 template<typename T>
2401 class CompositeGenerator {
2402 public:
CompositeGenerator()2403 CompositeGenerator() : m_totalSize(0) {}
2404
2405 // *** Move semantics, similar to auto_ptr ***
CompositeGenerator(CompositeGenerator & other)2406 CompositeGenerator(CompositeGenerator& other)
2407 : m_fileInfo(other.m_fileInfo),
2408 m_totalSize(0)
2409 {
2410 move(other);
2411 }
2412
setFileInfo(const char * fileInfo)2413 CompositeGenerator& setFileInfo(const char* fileInfo) {
2414 m_fileInfo = fileInfo;
2415 return *this;
2416 }
2417
~CompositeGenerator()2418 ~CompositeGenerator() {
2419 deleteAll(m_composed);
2420 }
2421
operator T() const2422 operator T () const {
2423 size_t overallIndex = getCurrentContext().getGeneratorIndex(m_fileInfo, m_totalSize);
2424
2425 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2426 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2427 for (size_t index = 0; it != itEnd; ++it)
2428 {
2429 const IGenerator<T>* generator = *it;
2430 if (overallIndex >= index && overallIndex < index + generator->size())
2431 {
2432 return generator->getValue(overallIndex - index);
2433 }
2434 index += generator->size();
2435 }
2436 CATCH_INTERNAL_ERROR("Indexed past end of generated range");
2437 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
2438 }
2439
add(const IGenerator<T> * generator)2440 void add(const IGenerator<T>* generator) {
2441 m_totalSize += generator->size();
2442 m_composed.push_back(generator);
2443 }
2444
then(CompositeGenerator & other)2445 CompositeGenerator& then(CompositeGenerator& other) {
2446 move(other);
2447 return *this;
2448 }
2449
then(T value)2450 CompositeGenerator& then(T value) {
2451 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2452 valuesGen->add(value);
2453 add(valuesGen);
2454 return *this;
2455 }
2456
2457 private:
2458
move(CompositeGenerator & other)2459 void move(CompositeGenerator& other) {
2460 std::copy(other.m_composed.begin(), other.m_composed.end(), std::back_inserter(m_composed));
2461 m_totalSize += other.m_totalSize;
2462 other.m_composed.clear();
2463 }
2464
2465 std::vector<const IGenerator<T>*> m_composed;
2466 std::string m_fileInfo;
2467 size_t m_totalSize;
2468 };
2469
2470 namespace Generators
2471 {
2472 template<typename T>
between(T from,T to)2473 CompositeGenerator<T> between(T from, T to) {
2474 CompositeGenerator<T> generators;
2475 generators.add(new BetweenGenerator<T>(from, to));
2476 return generators;
2477 }
2478
2479 template<typename T>
values(T val1,T val2)2480 CompositeGenerator<T> values(T val1, T val2) {
2481 CompositeGenerator<T> generators;
2482 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2483 valuesGen->add(val1);
2484 valuesGen->add(val2);
2485 generators.add(valuesGen);
2486 return generators;
2487 }
2488
2489 template<typename T>
values(T val1,T val2,T val3)2490 CompositeGenerator<T> values(T val1, T val2, T val3){
2491 CompositeGenerator<T> generators;
2492 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2493 valuesGen->add(val1);
2494 valuesGen->add(val2);
2495 valuesGen->add(val3);
2496 generators.add(valuesGen);
2497 return generators;
2498 }
2499
2500 template<typename T>
values(T val1,T val2,T val3,T val4)2501 CompositeGenerator<T> values(T val1, T val2, T val3, T val4) {
2502 CompositeGenerator<T> generators;
2503 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2504 valuesGen->add(val1);
2505 valuesGen->add(val2);
2506 valuesGen->add(val3);
2507 valuesGen->add(val4);
2508 generators.add(valuesGen);
2509 return generators;
2510 }
2511
2512 } // end namespace Generators
2513
2514 using namespace Generators;
2515
2516 } // end namespace Catch
2517
2518 #define INTERNAL_CATCH_LINESTR2( line ) #line
2519 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2520
2521 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2522
2523 // #included from: internal/catch_interfaces_exception.h
2524 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2525
2526 #include <string>
2527 #include <vector>
2528
2529 // #included from: catch_interfaces_registry_hub.h
2530 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2531
2532 #include <string>
2533
2534 namespace Catch {
2535
2536 class TestCase;
2537 struct ITestCaseRegistry;
2538 struct IExceptionTranslatorRegistry;
2539 struct IExceptionTranslator;
2540 struct IReporterRegistry;
2541 struct IReporterFactory;
2542
2543 struct IRegistryHub {
2544 virtual ~IRegistryHub();
2545
2546 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2547 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2548 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2549 };
2550
2551 struct IMutableRegistryHub {
2552 virtual ~IMutableRegistryHub();
2553 virtual void registerReporter(std::string const& name, Ptr<IReporterFactory> const& factory) = 0;
2554 virtual void registerListener(Ptr<IReporterFactory> const& factory) = 0;
2555 virtual void registerTest(TestCase const& testInfo) = 0;
2556 virtual void registerTranslator(const IExceptionTranslator* translator) = 0;
2557 };
2558
2559 IRegistryHub& getRegistryHub();
2560 IMutableRegistryHub& getMutableRegistryHub();
2561 void cleanUp();
2562 std::string translateActiveException();
2563
2564 }
2565
2566 namespace Catch {
2567
2568 typedef std::string(*exceptionTranslateFunction)();
2569
2570 struct IExceptionTranslator;
2571 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2572
2573 struct IExceptionTranslator {
2574 virtual ~IExceptionTranslator();
2575 virtual std::string translate(ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd) const = 0;
2576 };
2577
2578 struct IExceptionTranslatorRegistry {
2579 virtual ~IExceptionTranslatorRegistry();
2580
2581 virtual std::string translateActiveException() const = 0;
2582 };
2583
2584 class ExceptionTranslatorRegistrar {
2585 template<typename T>
2586 class ExceptionTranslator : public IExceptionTranslator {
2587 public:
2588
ExceptionTranslator(std::string (* translateFunction)(T &))2589 ExceptionTranslator(std::string(*translateFunction)(T&))
2590 : m_translateFunction(translateFunction)
2591 {}
2592
translate(ExceptionTranslators::const_iterator it,ExceptionTranslators::const_iterator itEnd) const2593 virtual std::string translate(ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd) const CATCH_OVERRIDE{
2594 try {
2595 if (it == itEnd)
2596 throw;
2597 else
2598 return (*it)->translate(it + 1, itEnd);
2599 }
2600 catch (T& ex) {
2601 return m_translateFunction(ex);
2602 }
2603 }
2604
2605 protected:
2606 std::string(*m_translateFunction)(T&);
2607 };
2608
2609 public:
2610 template<typename T>
ExceptionTranslatorRegistrar(std::string (* translateFunction)(T &))2611 ExceptionTranslatorRegistrar(std::string(*translateFunction)(T&)) {
2612 getMutableRegistryHub().registerTranslator
2613 (new ExceptionTranslator<T>(translateFunction));
2614 }
2615 };
2616 }
2617
2618 ///////////////////////////////////////////////////////////////////////////////
2619 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
2620 static std::string translatorName( signature ); \
2621 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
2622 static std::string translatorName( signature )
2623
2624 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
2625
2626 // #included from: internal/catch_approx.hpp
2627 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2628
2629 #include <cmath>
2630 #include <limits>
2631
2632 namespace Catch {
2633 namespace Detail {
2634
2635 class Approx {
2636 public:
Approx(double value)2637 explicit Approx(double value)
2638 : m_epsilon(std::numeric_limits<float>::epsilon() * 100),
2639 m_scale(1.0),
2640 m_value(value)
2641 {}
2642
Approx(Approx const & other)2643 Approx(Approx const& other)
2644 : m_epsilon(other.m_epsilon),
2645 m_scale(other.m_scale),
2646 m_value(other.m_value)
2647 {}
2648
custom()2649 static Approx custom() {
2650 return Approx(0);
2651 }
2652
operator ()(double value)2653 Approx operator()(double value) {
2654 Approx approx(value);
2655 approx.epsilon(m_epsilon);
2656 approx.scale(m_scale);
2657 return approx;
2658 }
2659
operator ==(double lhs,Approx const & rhs)2660 friend bool operator == (double lhs, Approx const& rhs) {
2661 // Thanks to Richard Harris for his help refining this formula
2662 return fabs(lhs - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(fabs(lhs), fabs(rhs.m_value)));
2663 }
2664
operator ==(Approx const & lhs,double rhs)2665 friend bool operator == (Approx const& lhs, double rhs) {
2666 return operator==(rhs, lhs);
2667 }
2668
operator !=(double lhs,Approx const & rhs)2669 friend bool operator != (double lhs, Approx const& rhs) {
2670 return !operator==(lhs, rhs);
2671 }
2672
operator !=(Approx const & lhs,double rhs)2673 friend bool operator != (Approx const& lhs, double rhs) {
2674 return !operator==(rhs, lhs);
2675 }
2676
epsilon(double newEpsilon)2677 Approx& epsilon(double newEpsilon) {
2678 m_epsilon = newEpsilon;
2679 return *this;
2680 }
2681
scale(double newScale)2682 Approx& scale(double newScale) {
2683 m_scale = newScale;
2684 return *this;
2685 }
2686
toString() const2687 std::string toString() const {
2688 std::ostringstream oss;
2689 oss << "Approx( " << Catch::toString(m_value) << " )";
2690 return oss.str();
2691 }
2692
2693 private:
2694 double m_epsilon;
2695 double m_scale;
2696 double m_value;
2697 };
2698 }
2699
2700 template<>
toString(Detail::Approx const & value)2701 inline std::string toString<Detail::Approx>(Detail::Approx const& value) {
2702 return value.toString();
2703 }
2704
2705 } // end namespace Catch
2706
2707 // #included from: internal/catch_interfaces_tag_alias_registry.h
2708 #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
2709
2710 // #included from: catch_tag_alias.h
2711 #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
2712
2713 #include <string>
2714
2715 namespace Catch {
2716
2717 struct TagAlias {
TagAliasCatch::TagAlias2718 TagAlias(std::string _tag, SourceLineInfo _lineInfo) : tag(_tag), lineInfo(_lineInfo) {}
2719
2720 std::string tag;
2721 SourceLineInfo lineInfo;
2722 };
2723
2724 struct RegistrarForTagAliases {
2725 RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo);
2726 };
2727
2728 } // end namespace Catch
2729
2730 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
2731 // #included from: catch_option.hpp
2732 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
2733
2734 namespace Catch {
2735
2736 // An optional type
2737 template<typename T>
2738 class Option {
2739 public:
Option()2740 Option() : nullableValue(CATCH_NULL) {}
Option(T const & _value)2741 Option(T const& _value)
2742 : nullableValue(new(storage)T(_value))
2743 {}
Option(Option const & _other)2744 Option(Option const& _other)
2745 : nullableValue(_other ? new(storage)T(*_other) : CATCH_NULL)
2746 {}
2747
~Option()2748 ~Option() {
2749 reset();
2750 }
2751
operator =(Option const & _other)2752 Option& operator= (Option const& _other) {
2753 if (&_other != this) {
2754 reset();
2755 if (_other)
2756 nullableValue = new(storage)T(*_other);
2757 }
2758 return *this;
2759 }
operator =(T const & _value)2760 Option& operator = (T const& _value) {
2761 reset();
2762 nullableValue = new(storage)T(_value);
2763 return *this;
2764 }
2765
reset()2766 void reset() {
2767 if (nullableValue)
2768 nullableValue->~T();
2769 nullableValue = CATCH_NULL;
2770 }
2771
operator *()2772 T& operator*() { return *nullableValue; }
operator *() const2773 T const& operator*() const { return *nullableValue; }
operator ->()2774 T* operator->() { return nullableValue; }
operator ->() const2775 const T* operator->() const { return nullableValue; }
2776
valueOr(T const & defaultValue) const2777 T valueOr(T const& defaultValue) const {
2778 return nullableValue ? *nullableValue : defaultValue;
2779 }
2780
some() const2781 bool some() const { return nullableValue != CATCH_NULL; }
none() const2782 bool none() const { return nullableValue == CATCH_NULL; }
2783
operator !() const2784 bool operator !() const { return nullableValue == CATCH_NULL; }
operator SafeBool::type() const2785 operator SafeBool::type() const {
2786 return SafeBool::makeSafe(some());
2787 }
2788
2789 private:
2790 T* nullableValue;
2791 char storage[sizeof(T)];
2792 };
2793
2794 } // end namespace Catch
2795
2796 namespace Catch {
2797
2798 struct ITagAliasRegistry {
2799 virtual ~ITagAliasRegistry();
2800 virtual Option<TagAlias> find(std::string const& alias) const = 0;
2801 virtual std::string expandAliases(std::string const& unexpandedTestSpec) const = 0;
2802
2803 static ITagAliasRegistry const& get();
2804 };
2805
2806 } // end namespace Catch
2807
2808 // These files are included here so the single_include script doesn't put them
2809 // in the conditionally compiled sections
2810 // #included from: internal/catch_test_case_info.h
2811 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
2812
2813 #include <string>
2814 #include <set>
2815
2816 #ifdef __clang__
2817 #pragma clang diagnostic push
2818 #pragma clang diagnostic ignored "-Wpadded"
2819 #endif
2820
2821 namespace Catch {
2822
2823 struct ITestCase;
2824
2825 struct TestCaseInfo {
2826 enum SpecialProperties{
2827 None = 0,
2828 IsHidden = 1 << 1,
2829 ShouldFail = 1 << 2,
2830 MayFail = 1 << 3,
2831 Throws = 1 << 4
2832 };
2833
2834 TestCaseInfo(std::string const& _name,
2835 std::string const& _className,
2836 std::string const& _description,
2837 std::set<std::string> const& _tags,
2838 SourceLineInfo const& _lineInfo);
2839
2840 TestCaseInfo(TestCaseInfo const& other);
2841
2842 friend void setTags(TestCaseInfo& testCaseInfo, std::set<std::string> const& tags);
2843
2844 bool isHidden() const;
2845 bool throws() const;
2846 bool okToFail() const;
2847 bool expectedToFail() const;
2848
2849 std::string name;
2850 std::string className;
2851 std::string description;
2852 std::set<std::string> tags;
2853 std::set<std::string> lcaseTags;
2854 std::string tagsAsString;
2855 SourceLineInfo lineInfo;
2856 SpecialProperties properties;
2857 };
2858
2859 class TestCase : public TestCaseInfo {
2860 public:
2861
2862 TestCase(ITestCase* testCase, TestCaseInfo const& info);
2863 TestCase(TestCase const& other);
2864
2865 TestCase withName(std::string const& _newName) const;
2866
2867 void invoke() const;
2868
2869 TestCaseInfo const& getTestCaseInfo() const;
2870
2871 void swap(TestCase& other);
2872 bool operator == (TestCase const& other) const;
2873 bool operator < (TestCase const& other) const;
2874 TestCase& operator = (TestCase const& other);
2875
2876 private:
2877 Ptr<ITestCase> test;
2878 };
2879
2880 TestCase makeTestCase(ITestCase* testCase,
2881 std::string const& className,
2882 std::string const& name,
2883 std::string const& description,
2884 SourceLineInfo const& lineInfo);
2885 }
2886
2887 #ifdef __clang__
2888 #pragma clang diagnostic pop
2889 #endif
2890
2891
2892 #ifdef __OBJC__
2893 // #included from: internal/catch_objc.hpp
2894 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2895
2896 #import <objc/runtime.h>
2897
2898 #include <string>
2899
2900 // NB. Any general catch headers included here must be included
2901 // in catch.hpp first to make sure they are included by the single
2902 // header for non obj-usage
2903
2904 ///////////////////////////////////////////////////////////////////////////////
2905 // This protocol is really only here for (self) documenting purposes, since
2906 // all its methods are optional.
2907 @protocol OcFixture
2908
2909 @optional
2910
2911 - (void)setUp;
2912 -(void)tearDown;
2913
2914 @end
2915
2916 namespace Catch {
2917
2918 class OcMethod : public SharedImpl<ITestCase> {
2919
2920 public:
OcMethod(Class cls,SEL sel)2921 OcMethod(Class cls, SEL sel) : m_cls(cls), m_sel(sel) {}
2922
invoke() const2923 virtual void invoke() const {
2924 id obj = [[m_cls alloc] init];
2925
2926 performOptionalSelector(obj, @selector(setUp));
2927 performOptionalSelector(obj, m_sel);
2928 performOptionalSelector(obj, @selector(tearDown));
2929
2930 arcSafeRelease(obj);
2931 }
2932 private:
~OcMethod()2933 virtual ~OcMethod() {}
2934
2935 Class m_cls;
2936 SEL m_sel;
2937 };
2938
2939 namespace Detail{
2940
getAnnotation(Class cls,std::string const & annotationName,std::string const & testCaseName)2941 inline std::string getAnnotation(Class cls,
2942 std::string const& annotationName,
2943 std::string const& testCaseName) {
2944 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2945 SEL sel = NSSelectorFromString(selStr);
2946 arcSafeRelease(selStr);
2947 id value = performOptionalSelector(cls, sel);
2948 if (value)
2949 return[(NSString*)value UTF8String];
2950 return "";
2951 }
2952 }
2953
registerTestMethods()2954 inline size_t registerTestMethods() {
2955 size_t noTestMethods = 0;
2956 int noClasses = objc_getClassList(CATCH_NULL, 0);
2957
2958 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc(sizeof(Class) * noClasses);
2959 objc_getClassList(classes, noClasses);
2960
2961 for (int c = 0; c < noClasses; c++) {
2962 Class cls = classes[c];
2963 {
2964 u_int count;
2965 Method* methods = class_copyMethodList(cls, &count);
2966 for (u_int m = 0; m < count; m++) {
2967 SEL selector = method_getName(methods[m]);
2968 std::string methodName = sel_getName(selector);
2969 if (startsWith(methodName, "Catch_TestCase_")) {
2970 std::string testCaseName = methodName.substr(15);
2971 std::string name = Detail::getAnnotation(cls, "Name", testCaseName);
2972 std::string desc = Detail::getAnnotation(cls, "Description", testCaseName);
2973 const char* className = class_getName(cls);
2974
2975 getMutableRegistryHub().registerTest(makeTestCase(new OcMethod(cls, selector), className, name.c_str(), desc.c_str(), SourceLineInfo()));
2976 noTestMethods++;
2977 }
2978 }
2979 free(methods);
2980 }
2981 }
2982 return noTestMethods;
2983 }
2984
2985 namespace Matchers {
2986 namespace Impl {
2987 namespace NSStringMatchers {
2988
2989 template<typename MatcherT>
2990 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder2991 StringHolder(NSString* substr) : m_substr([substr copy]){}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder2992 StringHolder(StringHolder const& other) : m_substr([other.m_substr copy]){}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder2993 StringHolder() {
2994 arcSafeRelease(m_substr);
2995 }
2996
2997 NSString* m_substr;
2998 };
2999
3000 struct Equals : StringHolder<Equals> {
EqualsCatch::Matchers::Impl::NSStringMatchers::Equals3001 Equals(NSString* substr) : StringHolder(substr){}
3002
matchCatch::Matchers::Impl::NSStringMatchers::Equals3003 virtual bool match(ExpressionType const& str) const {
3004 return (str != nil || m_substr == nil) &&
3005 [str isEqualToString : m_substr];
3006 }
3007
toStringCatch::Matchers::Impl::NSStringMatchers::Equals3008 virtual std::string toString() const {
3009 return "equals string: " + Catch::toString(m_substr);
3010 }
3011 };
3012
3013 struct Contains : StringHolder<Contains> {
ContainsCatch::Matchers::Impl::NSStringMatchers::Contains3014 Contains(NSString* substr) : StringHolder(substr){}
3015
matchCatch::Matchers::Impl::NSStringMatchers::Contains3016 virtual bool match(ExpressionType const& str) const {
3017 return (str != nil || m_substr == nil) &&
3018 [str rangeOfString : m_substr].location != NSNotFound;
3019 }
3020
toStringCatch::Matchers::Impl::NSStringMatchers::Contains3021 virtual std::string toString() const {
3022 return "contains string: " + Catch::toString(m_substr);
3023 }
3024 };
3025
3026 struct StartsWith : StringHolder<StartsWith> {
StartsWithCatch::Matchers::Impl::NSStringMatchers::StartsWith3027 StartsWith(NSString* substr) : StringHolder(substr){}
3028
matchCatch::Matchers::Impl::NSStringMatchers::StartsWith3029 virtual bool match(ExpressionType const& str) const {
3030 return (str != nil || m_substr == nil) &&
3031 [str rangeOfString : m_substr].location == 0;
3032 }
3033
toStringCatch::Matchers::Impl::NSStringMatchers::StartsWith3034 virtual std::string toString() const {
3035 return "starts with: " + Catch::toString(m_substr);
3036 }
3037 };
3038 struct EndsWith : StringHolder<EndsWith> {
EndsWithCatch::Matchers::Impl::NSStringMatchers::EndsWith3039 EndsWith(NSString* substr) : StringHolder(substr){}
3040
matchCatch::Matchers::Impl::NSStringMatchers::EndsWith3041 virtual bool match(ExpressionType const& str) const {
3042 return (str != nil || m_substr == nil) &&
3043 [str rangeOfString : m_substr].location == [str length] - [m_substr length];
3044 }
3045
toStringCatch::Matchers::Impl::NSStringMatchers::EndsWith3046 virtual std::string toString() const {
3047 return "ends with: " + Catch::toString(m_substr);
3048 }
3049 };
3050
3051 } // namespace NSStringMatchers
3052 } // namespace Impl
3053
3054 inline Impl::NSStringMatchers::Equals
Equals(NSString * substr)3055 Equals(NSString* substr){ return Impl::NSStringMatchers::Equals(substr); }
3056
3057 inline Impl::NSStringMatchers::Contains
Contains(NSString * substr)3058 Contains(NSString* substr){ return Impl::NSStringMatchers::Contains(substr); }
3059
3060 inline Impl::NSStringMatchers::StartsWith
StartsWith(NSString * substr)3061 StartsWith(NSString* substr){ return Impl::NSStringMatchers::StartsWith(substr); }
3062
3063 inline Impl::NSStringMatchers::EndsWith
EndsWith(NSString * substr)3064 EndsWith(NSString* substr){ return Impl::NSStringMatchers::EndsWith(substr); }
3065
3066 } // namespace Matchers
3067
3068 using namespace Matchers;
3069
3070 } // namespace Catch
3071
3072 ///////////////////////////////////////////////////////////////////////////////
3073 #define OC_TEST_CASE( name, desc )\
3074 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
3075 {\
3076 return @ name; \
3077 }\
3078 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
3079 { \
3080 return @ desc; \
3081 } \
3082 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3083
3084 #endif
3085
3086 #ifdef CATCH_IMPL
3087 // #included from: internal/catch_impl.hpp
3088 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
3089
3090 // Collect all the implementation files together here
3091 // These are the equivalent of what would usually be cpp files
3092
3093 #ifdef __clang__
3094 #pragma clang diagnostic push
3095 #pragma clang diagnostic ignored "-Wweak-vtables"
3096 #endif
3097
3098 // #included from: ../catch_session.hpp
3099 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
3100
3101 // #included from: internal/catch_commandline.hpp
3102 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3103
3104 // #included from: catch_config.hpp
3105 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3106
3107 // #included from: catch_test_spec_parser.hpp
3108 #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
3109
3110 #ifdef __clang__
3111 #pragma clang diagnostic push
3112 #pragma clang diagnostic ignored "-Wpadded"
3113 #endif
3114
3115 // #included from: catch_test_spec.hpp
3116 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
3117
3118 #ifdef __clang__
3119 #pragma clang diagnostic push
3120 #pragma clang diagnostic ignored "-Wpadded"
3121 #endif
3122
3123 // #included from: catch_wildcard_pattern.hpp
3124 #define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3125
3126 namespace Catch
3127 {
3128 class WildcardPattern {
3129 enum WildcardPosition {
3130 NoWildcard = 0,
3131 WildcardAtStart = 1,
3132 WildcardAtEnd = 2,
3133 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3134 };
3135
3136 public:
3137
WildcardPattern(std::string const & pattern,CaseSensitive::Choice caseSensitivity)3138 WildcardPattern(std::string const& pattern, CaseSensitive::Choice caseSensitivity)
3139 : m_caseSensitivity(caseSensitivity),
3140 m_wildcard(NoWildcard),
3141 m_pattern(adjustCase(pattern))
3142 {
3143 if (startsWith(m_pattern, "*")) {
3144 m_pattern = m_pattern.substr(1);
3145 m_wildcard = WildcardAtStart;
3146 }
3147 if (endsWith(m_pattern, "*")) {
3148 m_pattern = m_pattern.substr(0, m_pattern.size() - 1);
3149 m_wildcard = static_cast<WildcardPosition>(m_wildcard | WildcardAtEnd);
3150 }
3151 }
3152 virtual ~WildcardPattern();
matches(std::string const & str) const3153 virtual bool matches(std::string const& str) const {
3154 switch (m_wildcard) {
3155 case NoWildcard:
3156 return m_pattern == adjustCase(str);
3157 case WildcardAtStart:
3158 return endsWith(adjustCase(str), m_pattern);
3159 case WildcardAtEnd:
3160 return startsWith(adjustCase(str), m_pattern);
3161 case WildcardAtBothEnds:
3162 return contains(adjustCase(str), m_pattern);
3163 }
3164
3165 #ifdef __clang__
3166 #pragma clang diagnostic push
3167 #pragma clang diagnostic ignored "-Wunreachable-code"
3168 #endif
3169 throw std::logic_error("Unknown enum");
3170 #ifdef __clang__
3171 #pragma clang diagnostic pop
3172 #endif
3173 }
3174 private:
adjustCase(std::string const & str) const3175 std::string adjustCase(std::string const& str) const {
3176 return m_caseSensitivity == CaseSensitive::No ? toLower(str) : str;
3177 }
3178 CaseSensitive::Choice m_caseSensitivity;
3179 WildcardPosition m_wildcard;
3180 std::string m_pattern;
3181 };
3182 }
3183
3184 #include <string>
3185 #include <vector>
3186
3187 namespace Catch {
3188
3189 class TestSpec {
3190 struct Pattern : SharedImpl<> {
3191 virtual ~Pattern();
3192 virtual bool matches(TestCaseInfo const& testCase) const = 0;
3193 };
3194 class NamePattern : public Pattern {
3195 public:
NamePattern(std::string const & name)3196 NamePattern(std::string const& name)
3197 : m_wildcardPattern(toLower(name), CaseSensitive::No)
3198 {}
3199 virtual ~NamePattern();
matches(TestCaseInfo const & testCase) const3200 virtual bool matches(TestCaseInfo const& testCase) const {
3201 return m_wildcardPattern.matches(toLower(testCase.name));
3202 }
3203 private:
3204 WildcardPattern m_wildcardPattern;
3205 };
3206
3207 class TagPattern : public Pattern {
3208 public:
TagPattern(std::string const & tag)3209 TagPattern(std::string const& tag) : m_tag(toLower(tag)) {}
3210 virtual ~TagPattern();
matches(TestCaseInfo const & testCase) const3211 virtual bool matches(TestCaseInfo const& testCase) const {
3212 return testCase.lcaseTags.find(m_tag) != testCase.lcaseTags.end();
3213 }
3214 private:
3215 std::string m_tag;
3216 };
3217
3218 class ExcludedPattern : public Pattern {
3219 public:
ExcludedPattern(Ptr<Pattern> const & underlyingPattern)3220 ExcludedPattern(Ptr<Pattern> const& underlyingPattern) : m_underlyingPattern(underlyingPattern) {}
3221 virtual ~ExcludedPattern();
matches(TestCaseInfo const & testCase) const3222 virtual bool matches(TestCaseInfo const& testCase) const { return !m_underlyingPattern->matches(testCase); }
3223 private:
3224 Ptr<Pattern> m_underlyingPattern;
3225 };
3226
3227 struct Filter {
3228 std::vector<Ptr<Pattern> > m_patterns;
3229
matchesCatch::TestSpec::Filter3230 bool matches(TestCaseInfo const& testCase) const {
3231 // All patterns in a filter must match for the filter to be a match
3232 for (std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it)
3233 if (!(*it)->matches(testCase))
3234 return false;
3235 return true;
3236 }
3237 };
3238
3239 public:
hasFilters() const3240 bool hasFilters() const {
3241 return !m_filters.empty();
3242 }
matches(TestCaseInfo const & testCase) const3243 bool matches(TestCaseInfo const& testCase) const {
3244 // A TestSpec matches if any filter matches
3245 for (std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it)
3246 if (it->matches(testCase))
3247 return true;
3248 return false;
3249 }
3250
3251 private:
3252 std::vector<Filter> m_filters;
3253
3254 friend class TestSpecParser;
3255 };
3256 }
3257
3258 #ifdef __clang__
3259 #pragma clang diagnostic pop
3260 #endif
3261
3262 namespace Catch {
3263
3264 class TestSpecParser {
3265 enum Mode{ None, Name, QuotedName, Tag };
3266 Mode m_mode;
3267 bool m_exclusion;
3268 std::size_t m_start, m_pos;
3269 std::string m_arg;
3270 TestSpec::Filter m_currentFilter;
3271 TestSpec m_testSpec;
3272 ITagAliasRegistry const* m_tagAliases;
3273
3274 public:
TestSpecParser(ITagAliasRegistry const & tagAliases)3275 TestSpecParser(ITagAliasRegistry const& tagAliases) : m_tagAliases(&tagAliases) {}
3276
parse(std::string const & arg)3277 TestSpecParser& parse(std::string const& arg) {
3278 m_mode = None;
3279 m_exclusion = false;
3280 m_start = std::string::npos;
3281 m_arg = m_tagAliases->expandAliases(arg);
3282 for (m_pos = 0; m_pos < m_arg.size(); ++m_pos)
3283 visitChar(m_arg[m_pos]);
3284 if (m_mode == Name)
3285 addPattern<TestSpec::NamePattern>();
3286 return *this;
3287 }
testSpec()3288 TestSpec testSpec() {
3289 addFilter();
3290 return m_testSpec;
3291 }
3292 private:
visitChar(char c)3293 void visitChar(char c) {
3294 if (m_mode == None) {
3295 switch (c) {
3296 case ' ': return;
3297 case '~': m_exclusion = true; return;
3298 case '[': return startNewMode(Tag, ++m_pos);
3299 case '"': return startNewMode(QuotedName, ++m_pos);
3300 default: startNewMode(Name, m_pos); break;
3301 }
3302 }
3303 if (m_mode == Name) {
3304 if (c == ',') {
3305 addPattern<TestSpec::NamePattern>();
3306 addFilter();
3307 }
3308 else if (c == '[') {
3309 if (subString() == "exclude:")
3310 m_exclusion = true;
3311 else
3312 addPattern<TestSpec::NamePattern>();
3313 startNewMode(Tag, ++m_pos);
3314 }
3315 }
3316 else if (m_mode == QuotedName && c == '"')
3317 addPattern<TestSpec::NamePattern>();
3318 else if (m_mode == Tag && c == ']')
3319 addPattern<TestSpec::TagPattern>();
3320 }
startNewMode(Mode mode,std::size_t start)3321 void startNewMode(Mode mode, std::size_t start) {
3322 m_mode = mode;
3323 m_start = start;
3324 }
subString() const3325 std::string subString() const { return m_arg.substr(m_start, m_pos - m_start); }
3326 template<typename T>
addPattern()3327 void addPattern() {
3328 std::string token = subString();
3329 if (startsWith(token, "exclude:")) {
3330 m_exclusion = true;
3331 token = token.substr(8);
3332 }
3333 if (!token.empty()) {
3334 Ptr<TestSpec::Pattern> pattern = new T(token);
3335 if (m_exclusion)
3336 pattern = new TestSpec::ExcludedPattern(pattern);
3337 m_currentFilter.m_patterns.push_back(pattern);
3338 }
3339 m_exclusion = false;
3340 m_mode = None;
3341 }
addFilter()3342 void addFilter() {
3343 if (!m_currentFilter.m_patterns.empty()) {
3344 m_testSpec.m_filters.push_back(m_currentFilter);
3345 m_currentFilter = TestSpec::Filter();
3346 }
3347 }
3348 };
parseTestSpec(std::string const & arg)3349 inline TestSpec parseTestSpec(std::string const& arg) {
3350 return TestSpecParser(ITagAliasRegistry::get()).parse(arg).testSpec();
3351 }
3352
3353 } // namespace Catch
3354
3355 #ifdef __clang__
3356 #pragma clang diagnostic pop
3357 #endif
3358
3359 // #included from: catch_interfaces_config.h
3360 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3361
3362 #include <iostream>
3363 #include <string>
3364 #include <vector>
3365
3366 namespace Catch {
3367
3368 struct Verbosity {
3369 enum Level {
3370 NoOutput = 0,
3371 Quiet,
3372 Normal
3373 };
3374 };
3375
3376 struct WarnAbout {
3377 enum What {
3378 Nothing = 0x00,
3379 NoAssertions = 0x01
3380 };
3381 };
3382
3383 struct ShowDurations {
3384 enum OrNot {
3385 DefaultForReporter,
3386 Always,
3387 Never
3388 };
3389 };
3390 struct RunTests {
3391 enum InWhatOrder {
3392 InDeclarationOrder,
3393 InLexicographicalOrder,
3394 InRandomOrder
3395 };
3396 };
3397 struct UseColour {
3398 enum YesOrNo {
3399 Auto,
3400 Yes,
3401 No
3402 };
3403 };
3404
3405 class TestSpec;
3406
3407 struct IConfig : IShared {
3408
3409 virtual ~IConfig();
3410
3411 virtual bool allowThrows() const = 0;
3412 virtual std::ostream& stream() const = 0;
3413 virtual std::string name() const = 0;
3414 virtual bool includeSuccessfulResults() const = 0;
3415 virtual bool shouldDebugBreak() const = 0;
3416 virtual bool warnAboutMissingAssertions() const = 0;
3417 virtual int abortAfter() const = 0;
3418 virtual bool showInvisibles() const = 0;
3419 virtual ShowDurations::OrNot showDurations() const = 0;
3420 virtual TestSpec const& testSpec() const = 0;
3421 virtual RunTests::InWhatOrder runOrder() const = 0;
3422 virtual unsigned int rngSeed() const = 0;
3423 virtual UseColour::YesOrNo useColour() const = 0;
3424 };
3425 }
3426
3427 // #included from: catch_stream.h
3428 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3429
3430 // #included from: catch_streambuf.h
3431 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
3432
3433 #include <streambuf>
3434
3435 namespace Catch {
3436
3437 class StreamBufBase : public std::streambuf {
3438 public:
3439 virtual ~StreamBufBase() CATCH_NOEXCEPT;
3440 };
3441 }
3442
3443 #include <streambuf>
3444 #include <ostream>
3445 #include <fstream>
3446
3447 namespace Catch {
3448
3449 std::ostream& cout();
3450 std::ostream& cerr();
3451
3452 struct IStream {
3453 virtual ~IStream() CATCH_NOEXCEPT;
3454 virtual std::ostream& stream() const = 0;
3455 };
3456
3457 class FileStream : public IStream {
3458 mutable std::ofstream m_ofs;
3459 public:
3460 FileStream(std::string const& filename);
3461 virtual ~FileStream() CATCH_NOEXCEPT;
3462 public: // IStream
3463 virtual std::ostream& stream() const CATCH_OVERRIDE;
3464 };
3465
3466 class CoutStream : public IStream {
3467 mutable std::ostream m_os;
3468 public:
3469 CoutStream();
3470 virtual ~CoutStream() CATCH_NOEXCEPT;
3471
3472 public: // IStream
3473 virtual std::ostream& stream() const CATCH_OVERRIDE;
3474 };
3475
3476 class DebugOutStream : public IStream {
3477 CATCH_AUTO_PTR(StreamBufBase) m_streamBuf;
3478 mutable std::ostream m_os;
3479 public:
3480 DebugOutStream();
3481 virtual ~DebugOutStream() CATCH_NOEXCEPT;
3482
3483 public: // IStream
3484 virtual std::ostream& stream() const CATCH_OVERRIDE;
3485 };
3486 }
3487
3488 #include <memory>
3489 #include <vector>
3490 #include <string>
3491 #include <iostream>
3492 #include <ctime>
3493
3494 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
3495 #define CATCH_CONFIG_CONSOLE_WIDTH 80
3496 #endif
3497
3498 namespace Catch {
3499
3500 struct ConfigData {
3501
ConfigDataCatch::ConfigData3502 ConfigData()
3503 : listTests(false),
3504 listTags(false),
3505 listReporters(false),
3506 listTestNamesOnly(false),
3507 showSuccessfulTests(false),
3508 shouldDebugBreak(false),
3509 noThrow(false),
3510 showHelp(false),
3511 showInvisibles(false),
3512 filenamesAsTags(false),
3513 abortAfter(-1),
3514 rngSeed(0),
3515 verbosity(Verbosity::Normal),
3516 warnings(WarnAbout::Nothing),
3517 showDurations(ShowDurations::DefaultForReporter),
3518 runOrder(RunTests::InDeclarationOrder),
3519 useColour(UseColour::Auto)
3520 {}
3521
3522 bool listTests;
3523 bool listTags;
3524 bool listReporters;
3525 bool listTestNamesOnly;
3526
3527 bool showSuccessfulTests;
3528 bool shouldDebugBreak;
3529 bool noThrow;
3530 bool showHelp;
3531 bool showInvisibles;
3532 bool filenamesAsTags;
3533
3534 int abortAfter;
3535 unsigned int rngSeed;
3536
3537 Verbosity::Level verbosity;
3538 WarnAbout::What warnings;
3539 ShowDurations::OrNot showDurations;
3540 RunTests::InWhatOrder runOrder;
3541 UseColour::YesOrNo useColour;
3542
3543 std::string outputFilename;
3544 std::string name;
3545 std::string processName;
3546
3547 std::vector<std::string> reporterNames;
3548 std::vector<std::string> testsOrTags;
3549 };
3550
3551 class Config : public SharedImpl<IConfig> {
3552 private:
3553 Config(Config const& other);
3554 Config& operator = (Config const& other);
3555 virtual void dummy();
3556 public:
3557
Config()3558 Config()
3559 {}
3560
Config(ConfigData const & data)3561 Config(ConfigData const& data)
3562 : m_data(data),
3563 m_stream(openStream())
3564 {
3565 if (!data.testsOrTags.empty()) {
3566 TestSpecParser parser(ITagAliasRegistry::get());
3567 for (std::size_t i = 0; i < data.testsOrTags.size(); ++i)
3568 parser.parse(data.testsOrTags[i]);
3569 m_testSpec = parser.testSpec();
3570 }
3571 }
3572
~Config()3573 virtual ~Config() {
3574 }
3575
getFilename() const3576 std::string const& getFilename() const {
3577 return m_data.outputFilename;
3578 }
3579
listTests() const3580 bool listTests() const { return m_data.listTests; }
listTestNamesOnly() const3581 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
listTags() const3582 bool listTags() const { return m_data.listTags; }
listReporters() const3583 bool listReporters() const { return m_data.listReporters; }
3584
getProcessName() const3585 std::string getProcessName() const { return m_data.processName; }
3586
shouldDebugBreak() const3587 bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
3588
getReporterNames() const3589 std::vector<std::string> getReporterNames() const { return m_data.reporterNames; }
3590
abortAfter() const3591 int abortAfter() const { return m_data.abortAfter; }
3592
testSpec() const3593 TestSpec const& testSpec() const { return m_testSpec; }
3594
showHelp() const3595 bool showHelp() const { return m_data.showHelp; }
showInvisibles() const3596 bool showInvisibles() const { return m_data.showInvisibles; }
3597
3598 // IConfig interface
allowThrows() const3599 virtual bool allowThrows() const { return !m_data.noThrow; }
stream() const3600 virtual std::ostream& stream() const { return m_stream->stream(); }
name() const3601 virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
includeSuccessfulResults() const3602 virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
warnAboutMissingAssertions() const3603 virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
showDurations() const3604 virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
runOrder() const3605 virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
rngSeed() const3606 virtual unsigned int rngSeed() const { return m_data.rngSeed; }
useColour() const3607 virtual UseColour::YesOrNo useColour() const { return m_data.useColour; }
3608
3609 private:
3610
openStream()3611 IStream const* openStream() {
3612 if (m_data.outputFilename.empty())
3613 return new CoutStream();
3614 else if (m_data.outputFilename[0] == '%') {
3615 if (m_data.outputFilename == "%debug")
3616 return new DebugOutStream();
3617 else
3618 throw std::domain_error("Unrecognised stream: " + m_data.outputFilename);
3619 }
3620 else
3621 return new FileStream(m_data.outputFilename);
3622 }
3623 ConfigData m_data;
3624
3625 CATCH_AUTO_PTR(IStream const) m_stream;
3626 TestSpec m_testSpec;
3627 };
3628
3629 } // end namespace Catch
3630
3631 // #included from: catch_clara.h
3632 #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
3633
3634 // Use Catch's value for console width (store Clara's off to the side, if present)
3635 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
3636 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
3637 #undef CLARA_CONFIG_CONSOLE_WIDTH
3638 #endif
3639 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
3640
3641 // Declare Clara inside the Catch namespace
3642 #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
3643 // #included from: ../external/clara.h
3644
3645 // Version 0.0.2.4
3646
3647 // Only use header guard if we are not using an outer namespace
3648 #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
3649
3650 #ifndef STITCH_CLARA_OPEN_NAMESPACE
3651 #define TWOBLUECUBES_CLARA_H_INCLUDED
3652 #define STITCH_CLARA_OPEN_NAMESPACE
3653 #define STITCH_CLARA_CLOSE_NAMESPACE
3654 #else
3655 #define STITCH_CLARA_CLOSE_NAMESPACE }
3656 #endif
3657
3658 #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
3659
3660 // ----------- #included from tbc_text_format.h -----------
3661
3662 // Only use header guard if we are not using an outer namespace
3663 #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
3664 #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3665 #define TBC_TEXT_FORMAT_H_INCLUDED
3666 #endif
3667
3668 #include <string>
3669 #include <vector>
3670 #include <sstream>
3671 #include <algorithm>
3672
3673 // Use optional outer namespace
3674 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3675 namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
3676 #endif
3677
3678 namespace Tbc {
3679
3680 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
3681 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
3682 #else
3683 const unsigned int consoleWidth = 80;
3684 #endif
3685
3686 struct TextAttributes {
TextAttributesSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3687 TextAttributes()
3688 : initialIndent(std::string::npos),
3689 indent(0),
3690 width(consoleWidth - 1),
3691 tabChar('\t')
3692 {}
3693
setInitialIndentSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3694 TextAttributes& setInitialIndent(std::size_t _value) { initialIndent = _value; return *this; }
setIndentSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3695 TextAttributes& setIndent(std::size_t _value) { indent = _value; return *this; }
setWidthSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3696 TextAttributes& setWidth(std::size_t _value) { width = _value; return *this; }
setTabCharSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes3697 TextAttributes& setTabChar(char _value) { tabChar = _value; return *this; }
3698
3699 std::size_t initialIndent; // indent of first line, or npos
3700 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
3701 std::size_t width; // maximum width of text, including indent. Longer text will wrap
3702 char tabChar; // If this char is seen the indent is changed to current pos
3703 };
3704
3705 class Text {
3706 public:
Text(std::string const & _str,TextAttributes const & _attr=TextAttributes ())3707 Text(std::string const& _str, TextAttributes const& _attr = TextAttributes())
3708 : attr(_attr)
3709 {
3710 std::string wrappableChars = " [({.,/|\\-";
3711 std::size_t indent = _attr.initialIndent != std::string::npos
3712 ? _attr.initialIndent
3713 : _attr.indent;
3714 std::string remainder = _str;
3715
3716 while (!remainder.empty()) {
3717 if (lines.size() >= 1000) {
3718 lines.push_back("... message truncated due to excessive size");
3719 return;
3720 }
3721 std::size_t tabPos = std::string::npos;
3722 std::size_t width = (std::min)(remainder.size(), _attr.width - indent);
3723 std::size_t pos = remainder.find_first_of('\n');
3724 if (pos <= width) {
3725 width = pos;
3726 }
3727 pos = remainder.find_last_of(_attr.tabChar, width);
3728 if (pos != std::string::npos) {
3729 tabPos = pos;
3730 if (remainder[width] == '\n')
3731 width--;
3732 remainder = remainder.substr(0, tabPos) + remainder.substr(tabPos + 1);
3733 }
3734
3735 if (width == remainder.size()) {
3736 spliceLine(indent, remainder, width);
3737 }
3738 else if (remainder[width] == '\n') {
3739 spliceLine(indent, remainder, width);
3740 if (width <= 1 || remainder.size() != 1)
3741 remainder = remainder.substr(1);
3742 indent = _attr.indent;
3743 }
3744 else {
3745 pos = remainder.find_last_of(wrappableChars, width);
3746 if (pos != std::string::npos && pos > 0) {
3747 spliceLine(indent, remainder, pos);
3748 if (remainder[0] == ' ')
3749 remainder = remainder.substr(1);
3750 }
3751 else {
3752 spliceLine(indent, remainder, width - 1);
3753 lines.back() += "-";
3754 }
3755 if (lines.size() == 1)
3756 indent = _attr.indent;
3757 if (tabPos != std::string::npos)
3758 indent += tabPos;
3759 }
3760 }
3761 }
3762
spliceLine(std::size_t _indent,std::string & _remainder,std::size_t _pos)3763 void spliceLine(std::size_t _indent, std::string& _remainder, std::size_t _pos) {
3764 lines.push_back(std::string(_indent, ' ') + _remainder.substr(0, _pos));
3765 _remainder = _remainder.substr(_pos);
3766 }
3767
3768 typedef std::vector<std::string>::const_iterator const_iterator;
3769
begin() const3770 const_iterator begin() const { return lines.begin(); }
end() const3771 const_iterator end() const { return lines.end(); }
last() const3772 std::string const& last() const { return lines.back(); }
size() const3773 std::size_t size() const { return lines.size(); }
operator [](std::size_t _index) const3774 std::string const& operator[](std::size_t _index) const { return lines[_index]; }
toString() const3775 std::string toString() const {
3776 std::ostringstream oss;
3777 oss << *this;
3778 return oss.str();
3779 }
3780
operator <<(std::ostream & _stream,Text const & _text)3781 inline friend std::ostream& operator << (std::ostream& _stream, Text const& _text) {
3782 for (Text::const_iterator it = _text.begin(), itEnd = _text.end();
3783 it != itEnd; ++it) {
3784 if (it != _text.begin())
3785 _stream << "\n";
3786 _stream << *it;
3787 }
3788 return _stream;
3789 }
3790
3791 private:
3792 std::string str;
3793 TextAttributes attr;
3794 std::vector<std::string> lines;
3795 };
3796
3797 } // end namespace Tbc
3798
3799 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3800 } // end outer namespace
3801 #endif
3802
3803 #endif // TBC_TEXT_FORMAT_H_INCLUDED
3804
3805 // ----------- end of #include from tbc_text_format.h -----------
3806 // ........... back in clara.h
3807
3808 #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
3809
3810 // ----------- #included from clara_compilers.h -----------
3811
3812 #ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
3813 #define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
3814
3815 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler
3816 // The following features are defined:
3817 //
3818 // CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
3819 // CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
3820 // CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
3821 // CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
3822 // CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
3823
3824 // CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
3825
3826 // CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
3827
3828 // In general each macro has a _NO_<feature name> form
3829 // (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
3830 // Many features, at point of detection, define an _INTERNAL_ macro, so they
3831 // can be combined, en-mass, with the _NO_ forms later.
3832
3833 // All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
3834
3835 #ifdef __clang__
3836
3837 #if __has_feature(cxx_nullptr)
3838 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3839 #endif
3840
3841 #if __has_feature(cxx_noexcept)
3842 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3843 #endif
3844
3845 #endif // __clang__
3846
3847 ////////////////////////////////////////////////////////////////////////////////
3848 // GCC
3849 #ifdef __GNUC__
3850
3851 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
3852 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3853 #endif
3854
3855 // - otherwise more recent versions define __cplusplus >= 201103L
3856 // and will get picked up below
3857
3858 #endif // __GNUC__
3859
3860 ////////////////////////////////////////////////////////////////////////////////
3861 // Visual C++
3862 #ifdef _MSC_VER
3863
3864 #if (_MSC_VER >= 1600)
3865 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3866 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
3867 #endif
3868
3869 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
3870 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3871 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
3872 #endif
3873
3874 #endif // _MSC_VER
3875
3876 ////////////////////////////////////////////////////////////////////////////////
3877 // C++ language feature support
3878
3879 // catch all support for C++11
3880 #if defined(__cplusplus) && __cplusplus >= 201103L
3881
3882 #define CLARA_CPP11_OR_GREATER
3883
3884 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
3885 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3886 #endif
3887
3888 #ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3889 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3890 #endif
3891
3892 #ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
3893 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
3894 #endif
3895
3896 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
3897 #define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
3898 #endif
3899 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
3900 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
3901 #endif
3902
3903 #endif // __cplusplus >= 201103L
3904
3905 // Now set the actual defines based on the above + anything the user has configured
3906 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
3907 #define CLARA_CONFIG_CPP11_NULLPTR
3908 #endif
3909 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
3910 #define CLARA_CONFIG_CPP11_NOEXCEPT
3911 #endif
3912 #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)
3913 #define CLARA_CONFIG_CPP11_GENERATED_METHODS
3914 #endif
3915 #if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
3916 #define CLARA_CONFIG_CPP11_OVERRIDE
3917 #endif
3918 #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)
3919 #define CLARA_CONFIG_CPP11_UNIQUE_PTR
3920 #endif
3921
3922 // noexcept support:
3923 #if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
3924 #define CLARA_NOEXCEPT noexcept
3925 # define CLARA_NOEXCEPT_IS(x) noexcept(x)
3926 #else
3927 #define CLARA_NOEXCEPT throw()
3928 # define CLARA_NOEXCEPT_IS(x)
3929 #endif
3930
3931 // nullptr support
3932 #ifdef CLARA_CONFIG_CPP11_NULLPTR
3933 #define CLARA_NULL nullptr
3934 #else
3935 #define CLARA_NULL NULL
3936 #endif
3937
3938 // override support
3939 #ifdef CLARA_CONFIG_CPP11_OVERRIDE
3940 #define CLARA_OVERRIDE override
3941 #else
3942 #define CLARA_OVERRIDE
3943 #endif
3944
3945 // unique_ptr support
3946 #ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
3947 # define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
3948 #else
3949 # define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
3950 #endif
3951
3952 #endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
3953
3954 // ----------- end of #include from clara_compilers.h -----------
3955 // ........... back in clara.h
3956
3957 #include <map>
3958 #include <stdexcept>
3959 #include <memory>
3960
3961 #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
3962 #define CLARA_PLATFORM_WINDOWS
3963 #endif
3964
3965 // Use optional outer namespace
3966 #ifdef STITCH_CLARA_OPEN_NAMESPACE
3967 STITCH_CLARA_OPEN_NAMESPACE
3968 #endif
3969
3970 namespace Clara {
3971
3972 struct UnpositionalTag {};
3973
3974 extern UnpositionalTag _;
3975
3976 #ifdef CLARA_CONFIG_MAIN
3977 UnpositionalTag _;
3978 #endif
3979
3980 namespace Detail {
3981
3982 #ifdef CLARA_CONSOLE_WIDTH
3983 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
3984 #else
3985 const unsigned int consoleWidth = 80;
3986 #endif
3987
3988 using namespace Tbc;
3989
startsWith(std::string const & str,std::string const & prefix)3990 inline bool startsWith(std::string const& str, std::string const& prefix) {
3991 return str.size() >= prefix.size() && str.substr(0, prefix.size()) == prefix;
3992 }
3993
3994 template<typename T> struct RemoveConstRef{ typedef T type; };
3995 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
3996 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
3997 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
3998
3999 template<typename T> struct IsBool { static const bool value = false; };
4000 template<> struct IsBool<bool> { static const bool value = true; };
4001
4002 template<typename T>
convertInto(std::string const & _source,T & _dest)4003 void convertInto(std::string const& _source, T& _dest) {
4004 std::stringstream ss;
4005 ss << _source;
4006 ss >> _dest;
4007 if (ss.fail())
4008 throw std::runtime_error("Unable to convert " + _source + " to destination type");
4009 }
convertInto(std::string const & _source,std::string & _dest)4010 inline void convertInto(std::string const& _source, std::string& _dest) {
4011 _dest = _source;
4012 }
convertInto(std::string const & _source,bool & _dest)4013 inline void convertInto(std::string const& _source, bool& _dest) {
4014 std::string sourceLC = _source;
4015 std::transform(sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower);
4016 if (sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on")
4017 _dest = true;
4018 else if (sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off")
4019 _dest = false;
4020 else
4021 throw std::runtime_error("Expected a boolean value but did not recognise:\n '" + _source + "'");
4022 }
4023
4024 template<typename ConfigT>
4025 struct IArgFunction {
~IArgFunctionClara::Detail::IArgFunction4026 virtual ~IArgFunction() {}
4027 #ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
4028 IArgFunction() = default;
4029 IArgFunction(IArgFunction const&) = default;
4030 #endif
4031 virtual void set(ConfigT& config, std::string const& value) const = 0;
4032 virtual bool takesArg() const = 0;
4033 virtual IArgFunction* clone() const = 0;
4034 };
4035
4036 template<typename ConfigT>
4037 class BoundArgFunction {
4038 public:
BoundArgFunction()4039 BoundArgFunction() : functionObj(CLARA_NULL) {}
BoundArgFunction(IArgFunction<ConfigT> * _functionObj)4040 BoundArgFunction(IArgFunction<ConfigT>* _functionObj) : functionObj(_functionObj) {}
BoundArgFunction(BoundArgFunction const & other)4041 BoundArgFunction(BoundArgFunction const& other) : functionObj(other.functionObj ? other.functionObj->clone() : CLARA_NULL) {}
operator =(BoundArgFunction const & other)4042 BoundArgFunction& operator = (BoundArgFunction const& other) {
4043 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
4044 delete functionObj;
4045 functionObj = newFunctionObj;
4046 return *this;
4047 }
~BoundArgFunction()4048 ~BoundArgFunction() { delete functionObj; }
4049
set(ConfigT & config,std::string const & value) const4050 void set(ConfigT& config, std::string const& value) const {
4051 functionObj->set(config, value);
4052 }
takesArg() const4053 bool takesArg() const { return functionObj->takesArg(); }
4054
isSet() const4055 bool isSet() const {
4056 return functionObj != CLARA_NULL;
4057 }
4058 private:
4059 IArgFunction<ConfigT>* functionObj;
4060 };
4061
4062 template<typename C>
4063 struct NullBinder : IArgFunction<C>{
setClara::Detail::NullBinder4064 virtual void set(C&, std::string const&) const {}
takesArgClara::Detail::NullBinder4065 virtual bool takesArg() const { return true; }
cloneClara::Detail::NullBinder4066 virtual IArgFunction<C>* clone() const { return new NullBinder(*this); }
4067 };
4068
4069 template<typename C, typename M>
4070 struct BoundDataMember : IArgFunction<C>{
BoundDataMemberClara::Detail::BoundDataMember4071 BoundDataMember(M C::* _member) : member(_member) {}
setClara::Detail::BoundDataMember4072 virtual void set(C& p, std::string const& stringValue) const {
4073 convertInto(stringValue, p.*member);
4074 }
takesArgClara::Detail::BoundDataMember4075 virtual bool takesArg() const { return !IsBool<M>::value; }
cloneClara::Detail::BoundDataMember4076 virtual IArgFunction<C>* clone() const { return new BoundDataMember(*this); }
4077 M C::* member;
4078 };
4079 template<typename C, typename M>
4080 struct BoundUnaryMethod : IArgFunction<C>{
BoundUnaryMethodClara::Detail::BoundUnaryMethod4081 BoundUnaryMethod(void (C::*_member)(M)) : member(_member) {}
setClara::Detail::BoundUnaryMethod4082 virtual void set(C& p, std::string const& stringValue) const {
4083 typename RemoveConstRef<M>::type value;
4084 convertInto(stringValue, value);
4085 (p.*member)(value);
4086 }
takesArgClara::Detail::BoundUnaryMethod4087 virtual bool takesArg() const { return !IsBool<M>::value; }
cloneClara::Detail::BoundUnaryMethod4088 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod(*this); }
4089 void (C::*member)(M);
4090 };
4091 template<typename C>
4092 struct BoundNullaryMethod : IArgFunction<C>{
BoundNullaryMethodClara::Detail::BoundNullaryMethod4093 BoundNullaryMethod(void (C::*_member)()) : member(_member) {}
setClara::Detail::BoundNullaryMethod4094 virtual void set(C& p, std::string const& stringValue) const {
4095 bool value;
4096 convertInto(stringValue, value);
4097 if (value)
4098 (p.*member)();
4099 }
takesArgClara::Detail::BoundNullaryMethod4100 virtual bool takesArg() const { return false; }
cloneClara::Detail::BoundNullaryMethod4101 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod(*this); }
4102 void (C::*member)();
4103 };
4104
4105 template<typename C>
4106 struct BoundUnaryFunction : IArgFunction<C>{
BoundUnaryFunctionClara::Detail::BoundUnaryFunction4107 BoundUnaryFunction(void(*_function)(C&)) : function(_function) {}
setClara::Detail::BoundUnaryFunction4108 virtual void set(C& obj, std::string const& stringValue) const {
4109 bool value;
4110 convertInto(stringValue, value);
4111 if (value)
4112 function(obj);
4113 }
takesArgClara::Detail::BoundUnaryFunction4114 virtual bool takesArg() const { return false; }
cloneClara::Detail::BoundUnaryFunction4115 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction(*this); }
4116 void(*function)(C&);
4117 };
4118
4119 template<typename C, typename T>
4120 struct BoundBinaryFunction : IArgFunction<C>{
BoundBinaryFunctionClara::Detail::BoundBinaryFunction4121 BoundBinaryFunction(void(*_function)(C&, T)) : function(_function) {}
setClara::Detail::BoundBinaryFunction4122 virtual void set(C& obj, std::string const& stringValue) const {
4123 typename RemoveConstRef<T>::type value;
4124 convertInto(stringValue, value);
4125 function(obj, value);
4126 }
takesArgClara::Detail::BoundBinaryFunction4127 virtual bool takesArg() const { return !IsBool<T>::value; }
cloneClara::Detail::BoundBinaryFunction4128 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction(*this); }
4129 void(*function)(C&, T);
4130 };
4131
4132 } // namespace Detail
4133
argsToVector(int argc,char const * const * const argv)4134 inline std::vector<std::string> argsToVector(int argc, char const* const* const argv) {
4135 std::vector<std::string> args(static_cast<std::size_t>(argc));
4136 for (std::size_t i = 0; i < static_cast<std::size_t>(argc); ++i)
4137 args[i] = argv[i];
4138
4139 return args;
4140 }
4141
4142 class Parser {
4143 enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
4144 Mode mode;
4145 std::size_t from;
4146 bool inQuotes;
4147 public:
4148
4149 struct Token {
4150 enum Type { Positional, ShortOpt, LongOpt };
TokenClara::Parser::Token4151 Token(Type _type, std::string const& _data) : type(_type), data(_data) {}
4152 Type type;
4153 std::string data;
4154 };
4155
Parser()4156 Parser() : mode(None), from(0), inQuotes(false){}
4157
parseIntoTokens(std::vector<std::string> const & args,std::vector<Token> & tokens)4158 void parseIntoTokens(std::vector<std::string> const& args, std::vector<Token>& tokens) {
4159 const std::string doubleDash = "--";
4160 for (std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i)
4161 parseIntoTokens(args[i], tokens);
4162 }
4163
parseIntoTokens(std::string const & arg,std::vector<Token> & tokens)4164 void parseIntoTokens(std::string const& arg, std::vector<Token>& tokens) {
4165 for (std::size_t i = 0; i <= arg.size(); ++i) {
4166 char c = arg[i];
4167 if (c == '"')
4168 inQuotes = !inQuotes;
4169 mode = handleMode(i, c, arg, tokens);
4170 }
4171 }
handleMode(std::size_t i,char c,std::string const & arg,std::vector<Token> & tokens)4172 Mode handleMode(std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens) {
4173 switch (mode) {
4174 case None: return handleNone(i, c);
4175 case MaybeShortOpt: return handleMaybeShortOpt(i, c);
4176 case ShortOpt:
4177 case LongOpt:
4178 case SlashOpt: return handleOpt(i, c, arg, tokens);
4179 case Positional: return handlePositional(i, c, arg, tokens);
4180 default: throw std::logic_error("Unknown mode");
4181 }
4182 }
4183
handleNone(std::size_t i,char c)4184 Mode handleNone(std::size_t i, char c) {
4185 if (inQuotes) {
4186 from = i;
4187 return Positional;
4188 }
4189 switch (c) {
4190 case '-': return MaybeShortOpt;
4191 #ifdef CLARA_PLATFORM_WINDOWS
4192 case '/': from = i + 1; return SlashOpt;
4193 #endif
4194 default: from = i; return Positional;
4195 }
4196 }
handleMaybeShortOpt(std::size_t i,char c)4197 Mode handleMaybeShortOpt(std::size_t i, char c) {
4198 switch (c) {
4199 case '-': from = i + 1; return LongOpt;
4200 default: from = i; return ShortOpt;
4201 }
4202 }
handleOpt(std::size_t i,char c,std::string const & arg,std::vector<Token> & tokens)4203 Mode handleOpt(std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens) {
4204 if (std::string(":=\0", 3).find(c) == std::string::npos)
4205 return mode;
4206
4207 std::string optName = arg.substr(from, i - from);
4208 if (mode == ShortOpt)
4209 for (std::size_t j = 0; j < optName.size(); ++j)
4210 tokens.push_back(Token(Token::ShortOpt, optName.substr(j, 1)));
4211 else if (mode == SlashOpt && optName.size() == 1)
4212 tokens.push_back(Token(Token::ShortOpt, optName));
4213 else
4214 tokens.push_back(Token(Token::LongOpt, optName));
4215 return None;
4216 }
handlePositional(std::size_t i,char c,std::string const & arg,std::vector<Token> & tokens)4217 Mode handlePositional(std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens) {
4218 if (inQuotes || std::string("\0", 1).find(c) == std::string::npos)
4219 return mode;
4220
4221 std::string data = arg.substr(from, i - from);
4222 tokens.push_back(Token(Token::Positional, data));
4223 return None;
4224 }
4225 };
4226
4227 template<typename ConfigT>
4228 struct CommonArgProperties {
CommonArgPropertiesClara::CommonArgProperties4229 CommonArgProperties() {}
CommonArgPropertiesClara::CommonArgProperties4230 CommonArgProperties(Detail::BoundArgFunction<ConfigT> const& _boundField) : boundField(_boundField) {}
4231
4232 Detail::BoundArgFunction<ConfigT> boundField;
4233 std::string description;
4234 std::string detail;
4235 std::string placeholder; // Only value if boundField takes an arg
4236
takesArgClara::CommonArgProperties4237 bool takesArg() const {
4238 return !placeholder.empty();
4239 }
validateClara::CommonArgProperties4240 void validate() const {
4241 if (!boundField.isSet())
4242 throw std::logic_error("option not bound");
4243 }
4244 };
4245 struct OptionArgProperties {
4246 std::vector<std::string> shortNames;
4247 std::string longName;
4248
hasShortNameClara::OptionArgProperties4249 bool hasShortName(std::string const& shortName) const {
4250 return std::find(shortNames.begin(), shortNames.end(), shortName) != shortNames.end();
4251 }
hasLongNameClara::OptionArgProperties4252 bool hasLongName(std::string const& _longName) const {
4253 return _longName == longName;
4254 }
4255 };
4256 struct PositionalArgProperties {
PositionalArgPropertiesClara::PositionalArgProperties4257 PositionalArgProperties() : position(-1) {}
4258 int position; // -1 means non-positional (floating)
4259
isFixedPositionalClara::PositionalArgProperties4260 bool isFixedPositional() const {
4261 return position != -1;
4262 }
4263 };
4264
4265 template<typename ConfigT>
4266 class CommandLine {
4267
4268 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
ArgClara::CommandLine::Arg4269 Arg() {}
ArgClara::CommandLine::Arg4270 Arg(Detail::BoundArgFunction<ConfigT> const& _boundField) : CommonArgProperties<ConfigT>(_boundField) {}
4271
4272 using CommonArgProperties<ConfigT>::placeholder; // !TBD
4273
dbgNameClara::CommandLine::Arg4274 std::string dbgName() const {
4275 if (!longName.empty())
4276 return "--" + longName;
4277 if (!shortNames.empty())
4278 return "-" + shortNames[0];
4279 return "positional args";
4280 }
commandsClara::CommandLine::Arg4281 std::string commands() const {
4282 std::ostringstream oss;
4283 bool first = true;
4284 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4285 for (; it != itEnd; ++it) {
4286 if (first)
4287 first = false;
4288 else
4289 oss << ", ";
4290 oss << "-" << *it;
4291 }
4292 if (!longName.empty()) {
4293 if (!first)
4294 oss << ", ";
4295 oss << "--" << longName;
4296 }
4297 if (!placeholder.empty())
4298 oss << " <" << placeholder << ">";
4299 return oss.str();
4300 }
4301 };
4302
4303 typedef CLARA_AUTO_PTR(Arg) ArgAutoPtr;
4304
addOptName(Arg & arg,std::string const & optName)4305 friend void addOptName(Arg& arg, std::string const& optName)
4306 {
4307 if (optName.empty())
4308 return;
4309 if (Detail::startsWith(optName, "--")) {
4310 if (!arg.longName.empty())
4311 throw std::logic_error("Only one long opt may be specified. '"
4312 + arg.longName
4313 + "' already specified, now attempting to add '"
4314 + optName + "'");
4315 arg.longName = optName.substr(2);
4316 }
4317 else if (Detail::startsWith(optName, "-"))
4318 arg.shortNames.push_back(optName.substr(1));
4319 else
4320 throw std::logic_error("option must begin with - or --. Option was: '" + optName + "'");
4321 }
setPositionalArg(Arg & arg,int position)4322 friend void setPositionalArg(Arg& arg, int position)
4323 {
4324 arg.position = position;
4325 }
4326
4327 class ArgBuilder {
4328 public:
ArgBuilder(Arg * arg)4329 ArgBuilder(Arg* arg) : m_arg(arg) {}
4330
4331 // Bind a non-boolean data member (requires placeholder string)
4332 template<typename C, typename M>
bind(M C::* field,std::string const & placeholder)4333 void bind(M C::* field, std::string const& placeholder) {
4334 m_arg->boundField = new Detail::BoundDataMember<C, M>(field);
4335 m_arg->placeholder = placeholder;
4336 }
4337 // Bind a boolean data member (no placeholder required)
4338 template<typename C>
bind(bool C::* field)4339 void bind(bool C::* field) {
4340 m_arg->boundField = new Detail::BoundDataMember<C, bool>(field);
4341 }
4342
4343 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
4344 template<typename C, typename M>
bind(void (C::* unaryMethod)(M),std::string const & placeholder)4345 void bind(void (C::* unaryMethod)(M), std::string const& placeholder) {
4346 m_arg->boundField = new Detail::BoundUnaryMethod<C, M>(unaryMethod);
4347 m_arg->placeholder = placeholder;
4348 }
4349
4350 // Bind a method taking a single, boolean argument (no placeholder string required)
4351 template<typename C>
bind(void (C::* unaryMethod)(bool))4352 void bind(void (C::* unaryMethod)(bool)) {
4353 m_arg->boundField = new Detail::BoundUnaryMethod<C, bool>(unaryMethod);
4354 }
4355
4356 // Bind a method that takes no arguments (will be called if opt is present)
4357 template<typename C>
bind(void (C::* nullaryMethod)())4358 void bind(void (C::* nullaryMethod)()) {
4359 m_arg->boundField = new Detail::BoundNullaryMethod<C>(nullaryMethod);
4360 }
4361
4362 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
4363 template<typename C>
bind(void (* unaryFunction)(C &))4364 void bind(void(*unaryFunction)(C&)) {
4365 m_arg->boundField = new Detail::BoundUnaryFunction<C>(unaryFunction);
4366 }
4367
4368 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
4369 template<typename C, typename T>
bind(void (* binaryFunction)(C &,T),std::string const & placeholder)4370 void bind(void(*binaryFunction)(C&, T), std::string const& placeholder) {
4371 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>(binaryFunction);
4372 m_arg->placeholder = placeholder;
4373 }
4374
describe(std::string const & description)4375 ArgBuilder& describe(std::string const& description) {
4376 m_arg->description = description;
4377 return *this;
4378 }
detail(std::string const & detail)4379 ArgBuilder& detail(std::string const& detail) {
4380 m_arg->detail = detail;
4381 return *this;
4382 }
4383
4384 protected:
4385 Arg* m_arg;
4386 };
4387
4388 class OptBuilder : public ArgBuilder {
4389 public:
OptBuilder(Arg * arg)4390 OptBuilder(Arg* arg) : ArgBuilder(arg) {}
OptBuilder(OptBuilder & other)4391 OptBuilder(OptBuilder& other) : ArgBuilder(other) {}
4392
operator [](std::string const & optName)4393 OptBuilder& operator[](std::string const& optName) {
4394 addOptName(*ArgBuilder::m_arg, optName);
4395 return *this;
4396 }
4397 };
4398
4399 public:
4400
CommandLine()4401 CommandLine()
4402 : m_boundProcessName(new Detail::NullBinder<ConfigT>()),
4403 m_highestSpecifiedArgPosition(0),
4404 m_throwOnUnrecognisedTokens(false)
4405 {}
CommandLine(CommandLine const & other)4406 CommandLine(CommandLine const& other)
4407 : m_boundProcessName(other.m_boundProcessName),
4408 m_options(other.m_options),
4409 m_positionalArgs(other.m_positionalArgs),
4410 m_highestSpecifiedArgPosition(other.m_highestSpecifiedArgPosition),
4411 m_throwOnUnrecognisedTokens(other.m_throwOnUnrecognisedTokens)
4412 {
4413 if (other.m_floatingArg.get())
4414 m_floatingArg.reset(new Arg(*other.m_floatingArg));
4415 }
4416
setThrowOnUnrecognisedTokens(bool shouldThrow=true)4417 CommandLine& setThrowOnUnrecognisedTokens(bool shouldThrow = true) {
4418 m_throwOnUnrecognisedTokens = shouldThrow;
4419 return *this;
4420 }
4421
operator [](std::string const & optName)4422 OptBuilder operator[](std::string const& optName) {
4423 m_options.push_back(Arg());
4424 addOptName(m_options.back(), optName);
4425 OptBuilder builder(&m_options.back());
4426 return builder;
4427 }
4428
operator [](int position)4429 ArgBuilder operator[](int position) {
4430 m_positionalArgs.insert(std::make_pair(position, Arg()));
4431 if (position > m_highestSpecifiedArgPosition)
4432 m_highestSpecifiedArgPosition = position;
4433 setPositionalArg(m_positionalArgs[position], position);
4434 ArgBuilder builder(&m_positionalArgs[position]);
4435 return builder;
4436 }
4437
4438 // Invoke this with the _ instance
operator [](UnpositionalTag)4439 ArgBuilder operator[](UnpositionalTag) {
4440 if (m_floatingArg.get())
4441 throw std::logic_error("Only one unpositional argument can be added");
4442 m_floatingArg.reset(new Arg());
4443 ArgBuilder builder(m_floatingArg.get());
4444 return builder;
4445 }
4446
4447 template<typename C, typename M>
bindProcessName(M C::* field)4448 void bindProcessName(M C::* field) {
4449 m_boundProcessName = new Detail::BoundDataMember<C, M>(field);
4450 }
4451 template<typename C, typename M>
bindProcessName(void (C::* _unaryMethod)(M))4452 void bindProcessName(void (C::*_unaryMethod)(M)) {
4453 m_boundProcessName = new Detail::BoundUnaryMethod<C, M>(_unaryMethod);
4454 }
4455
optUsage(std::ostream & os,std::size_t indent=0,std::size_t width=Detail::consoleWidth) const4456 void optUsage(std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth) const {
4457 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4458 std::size_t maxWidth = 0;
4459 for (it = itBegin; it != itEnd; ++it)
4460 maxWidth = (std::max)(maxWidth, it->commands().size());
4461
4462 for (it = itBegin; it != itEnd; ++it) {
4463 Detail::Text usage(it->commands(), Detail::TextAttributes()
4464 .setWidth(maxWidth + indent)
4465 .setIndent(indent));
4466 Detail::Text desc(it->description, Detail::TextAttributes()
4467 .setWidth(width - maxWidth - 3));
4468
4469 for (std::size_t i = 0; i < (std::max)(usage.size(), desc.size()); ++i) {
4470 std::string usageCol = i < usage.size() ? usage[i] : "";
4471 os << usageCol;
4472
4473 if (i < desc.size() && !desc[i].empty())
4474 os << std::string(indent + 2 + maxWidth - usageCol.size(), ' ')
4475 << desc[i];
4476 os << "\n";
4477 }
4478 }
4479 }
optUsage() const4480 std::string optUsage() const {
4481 std::ostringstream oss;
4482 optUsage(oss);
4483 return oss.str();
4484 }
4485
argSynopsis(std::ostream & os) const4486 void argSynopsis(std::ostream& os) const {
4487 for (int i = 1; i <= m_highestSpecifiedArgPosition; ++i) {
4488 if (i > 1)
4489 os << " ";
4490 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find(i);
4491 if (it != m_positionalArgs.end())
4492 os << "<" << it->second.placeholder << ">";
4493 else if (m_floatingArg.get())
4494 os << "<" << m_floatingArg->placeholder << ">";
4495 else
4496 throw std::logic_error("non consecutive positional arguments with no floating args");
4497 }
4498 // !TBD No indication of mandatory args
4499 if (m_floatingArg.get()) {
4500 if (m_highestSpecifiedArgPosition > 1)
4501 os << " ";
4502 os << "[<" << m_floatingArg->placeholder << "> ...]";
4503 }
4504 }
argSynopsis() const4505 std::string argSynopsis() const {
4506 std::ostringstream oss;
4507 argSynopsis(oss);
4508 return oss.str();
4509 }
4510
usage(std::ostream & os,std::string const & procName) const4511 void usage(std::ostream& os, std::string const& procName) const {
4512 validate();
4513 os << "usage:\n " << procName << " ";
4514 argSynopsis(os);
4515 if (!m_options.empty()) {
4516 os << " [options]\n\nwhere options are: \n";
4517 optUsage(os, 2);
4518 }
4519 os << "\n";
4520 }
usage(std::string const & procName) const4521 std::string usage(std::string const& procName) const {
4522 std::ostringstream oss;
4523 usage(oss, procName);
4524 return oss.str();
4525 }
4526
parse(std::vector<std::string> const & args) const4527 ConfigT parse(std::vector<std::string> const& args) const {
4528 ConfigT config;
4529 parseInto(args, config);
4530 return config;
4531 }
4532
parseInto(std::vector<std::string> const & args,ConfigT & config) const4533 std::vector<Parser::Token> parseInto(std::vector<std::string> const& args, ConfigT& config) const {
4534 std::string processName = args[0];
4535 std::size_t lastSlash = processName.find_last_of("/\\");
4536 if (lastSlash != std::string::npos)
4537 processName = processName.substr(lastSlash + 1);
4538 m_boundProcessName.set(config, processName);
4539 std::vector<Parser::Token> tokens;
4540 Parser parser;
4541 parser.parseIntoTokens(args, tokens);
4542 return populate(tokens, config);
4543 }
4544
populate(std::vector<Parser::Token> const & tokens,ConfigT & config) const4545 std::vector<Parser::Token> populate(std::vector<Parser::Token> const& tokens, ConfigT& config) const {
4546 validate();
4547 std::vector<Parser::Token> unusedTokens = populateOptions(tokens, config);
4548 unusedTokens = populateFixedArgs(unusedTokens, config);
4549 unusedTokens = populateFloatingArgs(unusedTokens, config);
4550 return unusedTokens;
4551 }
4552
populateOptions(std::vector<Parser::Token> const & tokens,ConfigT & config) const4553 std::vector<Parser::Token> populateOptions(std::vector<Parser::Token> const& tokens, ConfigT& config) const {
4554 std::vector<Parser::Token> unusedTokens;
4555 std::vector<std::string> errors;
4556 for (std::size_t i = 0; i < tokens.size(); ++i) {
4557 Parser::Token const& token = tokens[i];
4558 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4559 for (; it != itEnd; ++it) {
4560 Arg const& arg = *it;
4561
4562 try {
4563 if ((token.type == Parser::Token::ShortOpt && arg.hasShortName(token.data)) ||
4564 (token.type == Parser::Token::LongOpt && arg.hasLongName(token.data))) {
4565 if (arg.takesArg()) {
4566 if (i == tokens.size() - 1 || tokens[i + 1].type != Parser::Token::Positional)
4567 errors.push_back("Expected argument to option: " + token.data);
4568 else
4569 arg.boundField.set(config, tokens[++i].data);
4570 }
4571 else {
4572 arg.boundField.set(config, "true");
4573 }
4574 break;
4575 }
4576 }
4577 catch (std::exception& ex) {
4578 errors.push_back(std::string(ex.what()) + "\n- while parsing: (" + arg.commands() + ")");
4579 }
4580 }
4581 if (it == itEnd) {
4582 if (token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens)
4583 unusedTokens.push_back(token);
4584 else if (errors.empty() && m_throwOnUnrecognisedTokens)
4585 errors.push_back("unrecognised option: " + token.data);
4586 }
4587 }
4588 if (!errors.empty()) {
4589 std::ostringstream oss;
4590 for (std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
4591 it != itEnd;
4592 ++it) {
4593 if (it != errors.begin())
4594 oss << "\n";
4595 oss << *it;
4596 }
4597 throw std::runtime_error(oss.str());
4598 }
4599 return unusedTokens;
4600 }
populateFixedArgs(std::vector<Parser::Token> const & tokens,ConfigT & config) const4601 std::vector<Parser::Token> populateFixedArgs(std::vector<Parser::Token> const& tokens, ConfigT& config) const {
4602 std::vector<Parser::Token> unusedTokens;
4603 int position = 1;
4604 for (std::size_t i = 0; i < tokens.size(); ++i) {
4605 Parser::Token const& token = tokens[i];
4606 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find(position);
4607 if (it != m_positionalArgs.end())
4608 it->second.boundField.set(config, token.data);
4609 else
4610 unusedTokens.push_back(token);
4611 if (token.type == Parser::Token::Positional)
4612 position++;
4613 }
4614 return unusedTokens;
4615 }
populateFloatingArgs(std::vector<Parser::Token> const & tokens,ConfigT & config) const4616 std::vector<Parser::Token> populateFloatingArgs(std::vector<Parser::Token> const& tokens, ConfigT& config) const {
4617 if (!m_floatingArg.get())
4618 return tokens;
4619 std::vector<Parser::Token> unusedTokens;
4620 for (std::size_t i = 0; i < tokens.size(); ++i) {
4621 Parser::Token const& token = tokens[i];
4622 if (token.type == Parser::Token::Positional)
4623 m_floatingArg->boundField.set(config, token.data);
4624 else
4625 unusedTokens.push_back(token);
4626 }
4627 return unusedTokens;
4628 }
4629
validate() const4630 void validate() const
4631 {
4632 if (m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get())
4633 throw std::logic_error("No options or arguments specified");
4634
4635 for (typename std::vector<Arg>::const_iterator it = m_options.begin(),
4636 itEnd = m_options.end();
4637 it != itEnd; ++it)
4638 it->validate();
4639 }
4640
4641 private:
4642 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
4643 std::vector<Arg> m_options;
4644 std::map<int, Arg> m_positionalArgs;
4645 ArgAutoPtr m_floatingArg;
4646 int m_highestSpecifiedArgPosition;
4647 bool m_throwOnUnrecognisedTokens;
4648 };
4649
4650 } // end namespace Clara
4651
4652 STITCH_CLARA_CLOSE_NAMESPACE
4653 #undef STITCH_CLARA_OPEN_NAMESPACE
4654 #undef STITCH_CLARA_CLOSE_NAMESPACE
4655
4656 #endif // TWOBLUECUBES_CLARA_H_INCLUDED
4657 #undef STITCH_CLARA_OPEN_NAMESPACE
4658
4659 // Restore Clara's value for console width, if present
4660 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4661 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4662 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4663 #endif
4664
4665 #include <fstream>
4666
4667 namespace Catch {
4668
abortAfterFirst(ConfigData & config)4669 inline void abortAfterFirst(ConfigData& config) { config.abortAfter = 1; }
abortAfterX(ConfigData & config,int x)4670 inline void abortAfterX(ConfigData& config, int x) {
4671 if (x < 1)
4672 throw std::runtime_error("Value after -x or --abortAfter must be greater than zero");
4673 config.abortAfter = x;
4674 }
addTestOrTags(ConfigData & config,std::string const & _testSpec)4675 inline void addTestOrTags(ConfigData& config, std::string const& _testSpec) { config.testsOrTags.push_back(_testSpec); }
addReporterName(ConfigData & config,std::string const & _reporterName)4676 inline void addReporterName(ConfigData& config, std::string const& _reporterName) { config.reporterNames.push_back(_reporterName); }
4677
addWarning(ConfigData & config,std::string const & _warning)4678 inline void addWarning(ConfigData& config, std::string const& _warning) {
4679 if (_warning == "NoAssertions")
4680 config.warnings = static_cast<WarnAbout::What>(config.warnings | WarnAbout::NoAssertions);
4681 else
4682 throw std::runtime_error("Unrecognised warning: '" + _warning + "'");
4683 }
setOrder(ConfigData & config,std::string const & order)4684 inline void setOrder(ConfigData& config, std::string const& order) {
4685 if (startsWith("declared", order))
4686 config.runOrder = RunTests::InDeclarationOrder;
4687 else if (startsWith("lexical", order))
4688 config.runOrder = RunTests::InLexicographicalOrder;
4689 else if (startsWith("random", order))
4690 config.runOrder = RunTests::InRandomOrder;
4691 else
4692 throw std::runtime_error("Unrecognised ordering: '" + order + "'");
4693 }
setRngSeed(ConfigData & config,std::string const & seed)4694 inline void setRngSeed(ConfigData& config, std::string const& seed) {
4695 if (seed == "time") {
4696 config.rngSeed = static_cast<unsigned int>(std::time(0));
4697 }
4698 else {
4699 std::stringstream ss;
4700 ss << seed;
4701 ss >> config.rngSeed;
4702 if (ss.fail())
4703 throw std::runtime_error("Argment to --rng-seed should be the word 'time' or a number");
4704 }
4705 }
setVerbosity(ConfigData & config,int level)4706 inline void setVerbosity(ConfigData& config, int level) {
4707 // !TBD: accept strings?
4708 config.verbosity = static_cast<Verbosity::Level>(level);
4709 }
setShowDurations(ConfigData & config,bool _showDurations)4710 inline void setShowDurations(ConfigData& config, bool _showDurations) {
4711 config.showDurations = _showDurations
4712 ? ShowDurations::Always
4713 : ShowDurations::Never;
4714 }
setUseColour(ConfigData & config,std::string const & value)4715 inline void setUseColour(ConfigData& config, std::string const& value) {
4716 std::string mode = toLower(value);
4717
4718 if (mode == "yes")
4719 config.useColour = UseColour::Yes;
4720 else if (mode == "no")
4721 config.useColour = UseColour::No;
4722 else if (mode == "auto")
4723 config.useColour = UseColour::Auto;
4724 else
4725 throw std::runtime_error("colour mode must be one of: auto, yes or no");
4726 }
forceColour(ConfigData & config)4727 inline void forceColour(ConfigData& config) {
4728 config.useColour = UseColour::Yes;
4729 }
loadTestNamesFromFile(ConfigData & config,std::string const & _filename)4730 inline void loadTestNamesFromFile(ConfigData& config, std::string const& _filename) {
4731 std::ifstream f(_filename.c_str());
4732 if (!f.is_open())
4733 throw std::domain_error("Unable to load input file: " + _filename);
4734
4735 std::string line;
4736 while (std::getline(f, line)) {
4737 line = trim(line);
4738 if (!line.empty() && !startsWith(line, "#"))
4739 addTestOrTags(config, "\"" + line + "\",");
4740 }
4741 }
4742
makeCommandLineParser()4743 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
4744
4745 using namespace Clara;
4746 CommandLine<ConfigData> cli;
4747
4748 cli.bindProcessName(&ConfigData::processName);
4749
4750 cli["-?"]["-h"]["--help"]
4751 .describe("display usage information")
4752 .bind(&ConfigData::showHelp);
4753
4754 cli["-l"]["--list-tests"]
4755 .describe("list all/matching test cases")
4756 .bind(&ConfigData::listTests);
4757
4758 cli["-t"]["--list-tags"]
4759 .describe("list all/matching tags")
4760 .bind(&ConfigData::listTags);
4761
4762 cli["-s"]["--success"]
4763 .describe("include successful tests in output")
4764 .bind(&ConfigData::showSuccessfulTests);
4765
4766 cli["-b"]["--break"]
4767 .describe("break into debugger on failure")
4768 .bind(&ConfigData::shouldDebugBreak);
4769
4770 cli["-e"]["--nothrow"]
4771 .describe("skip exception tests")
4772 .bind(&ConfigData::noThrow);
4773
4774 cli["-i"]["--invisibles"]
4775 .describe("show invisibles (tabs, newlines)")
4776 .bind(&ConfigData::showInvisibles);
4777
4778 cli["-o"]["--out"]
4779 .describe("output filename")
4780 .bind(&ConfigData::outputFilename, "filename");
4781
4782 cli["-r"]["--reporter"]
4783 // .placeholder( "name[:filename]" )
4784 .describe("reporter to use (defaults to console)")
4785 .bind(&addReporterName, "name");
4786
4787 cli["-n"]["--name"]
4788 .describe("suite name")
4789 .bind(&ConfigData::name, "name");
4790
4791 cli["-a"]["--abort"]
4792 .describe("abort at first failure")
4793 .bind(&abortAfterFirst);
4794
4795 cli["-x"]["--abortx"]
4796 .describe("abort after x failures")
4797 .bind(&abortAfterX, "no. failures");
4798
4799 cli["-w"]["--warn"]
4800 .describe("enable warnings")
4801 .bind(&addWarning, "warning name");
4802
4803 // - needs updating if reinstated
4804 // cli.into( &setVerbosity )
4805 // .describe( "level of verbosity (0=no output)" )
4806 // .shortOpt( "v")
4807 // .longOpt( "verbosity" )
4808 // .placeholder( "level" );
4809
4810 cli[_]
4811 .describe("which test or tests to use")
4812 .bind(&addTestOrTags, "test name, pattern or tags");
4813
4814 cli["-d"]["--durations"]
4815 .describe("show test durations")
4816 .bind(&setShowDurations, "yes|no");
4817
4818 cli["-f"]["--input-file"]
4819 .describe("load test names to run from a file")
4820 .bind(&loadTestNamesFromFile, "filename");
4821
4822 cli["-#"]["--filenames-as-tags"]
4823 .describe("adds a tag for the filename")
4824 .bind(&ConfigData::filenamesAsTags);
4825
4826 // Less common commands which don't have a short form
4827 cli["--list-test-names-only"]
4828 .describe("list all/matching test cases names only")
4829 .bind(&ConfigData::listTestNamesOnly);
4830
4831 cli["--list-reporters"]
4832 .describe("list all reporters")
4833 .bind(&ConfigData::listReporters);
4834
4835 cli["--order"]
4836 .describe("test case order (defaults to decl)")
4837 .bind(&setOrder, "decl|lex|rand");
4838
4839 cli["--rng-seed"]
4840 .describe("set a specific seed for random numbers")
4841 .bind(&setRngSeed, "'time'|number");
4842
4843 cli["--force-colour"]
4844 .describe("force colourised output (deprecated)")
4845 .bind(&forceColour);
4846
4847 cli["--use-colour"]
4848 .describe("should output be colourised")
4849 .bind(&setUseColour, "yes|no");
4850
4851 return cli;
4852 }
4853
4854 } // end namespace Catch
4855
4856 // #included from: internal/catch_list.hpp
4857 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4858
4859 // #included from: catch_text.h
4860 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
4861
4862 #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4863
4864 #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
4865 // #included from: ../external/tbc_text_format.h
4866 // Only use header guard if we are not using an outer namespace
4867 #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4868 # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4869 # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4870 # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4871 # endif
4872 # else
4873 # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4874 # endif
4875 #endif
4876 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4877 #include <string>
4878 #include <vector>
4879 #include <sstream>
4880
4881 // Use optional outer namespace
4882 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4883 namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4884 #endif
4885
4886 namespace Tbc {
4887
4888 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4889 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4890 #else
4891 const unsigned int consoleWidth = 80;
4892 #endif
4893
4894 struct TextAttributes {
TextAttributesCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4895 TextAttributes()
4896 : initialIndent(std::string::npos),
4897 indent(0),
4898 width(consoleWidth - 1),
4899 tabChar('\t')
4900 {}
4901
setInitialIndentCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4902 TextAttributes& setInitialIndent(std::size_t _value) { initialIndent = _value; return *this; }
setIndentCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4903 TextAttributes& setIndent(std::size_t _value) { indent = _value; return *this; }
setWidthCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4904 TextAttributes& setWidth(std::size_t _value) { width = _value; return *this; }
setTabCharCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4905 TextAttributes& setTabChar(char _value) { tabChar = _value; return *this; }
4906
4907 std::size_t initialIndent; // indent of first line, or npos
4908 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
4909 std::size_t width; // maximum width of text, including indent. Longer text will wrap
4910 char tabChar; // If this char is seen the indent is changed to current pos
4911 };
4912
4913 class Text {
4914 public:
Text(std::string const & _str,TextAttributes const & _attr=TextAttributes ())4915 Text(std::string const& _str, TextAttributes const& _attr = TextAttributes())
4916 : attr(_attr)
4917 {
4918 std::string wrappableChars = " [({.,/|\\-";
4919 std::size_t indent = _attr.initialIndent != std::string::npos
4920 ? _attr.initialIndent
4921 : _attr.indent;
4922 std::string remainder = _str;
4923
4924 while (!remainder.empty()) {
4925 if (lines.size() >= 1000) {
4926 lines.push_back("... message truncated due to excessive size");
4927 return;
4928 }
4929 std::size_t tabPos = std::string::npos;
4930 std::size_t width = (std::min)(remainder.size(), _attr.width - indent);
4931 std::size_t pos = remainder.find_first_of('\n');
4932 if (pos <= width) {
4933 width = pos;
4934 }
4935 pos = remainder.find_last_of(_attr.tabChar, width);
4936 if (pos != std::string::npos) {
4937 tabPos = pos;
4938 if (remainder[width] == '\n')
4939 width--;
4940 remainder = remainder.substr(0, tabPos) + remainder.substr(tabPos + 1);
4941 }
4942
4943 if (width == remainder.size()) {
4944 spliceLine(indent, remainder, width);
4945 }
4946 else if (remainder[width] == '\n') {
4947 spliceLine(indent, remainder, width);
4948 if (width <= 1 || remainder.size() != 1)
4949 remainder = remainder.substr(1);
4950 indent = _attr.indent;
4951 }
4952 else {
4953 pos = remainder.find_last_of(wrappableChars, width);
4954 if (pos != std::string::npos && pos > 0) {
4955 spliceLine(indent, remainder, pos);
4956 if (remainder[0] == ' ')
4957 remainder = remainder.substr(1);
4958 }
4959 else {
4960 spliceLine(indent, remainder, width - 1);
4961 lines.back() += "-";
4962 }
4963 if (lines.size() == 1)
4964 indent = _attr.indent;
4965 if (tabPos != std::string::npos)
4966 indent += tabPos;
4967 }
4968 }
4969 }
4970
spliceLine(std::size_t _indent,std::string & _remainder,std::size_t _pos)4971 void spliceLine(std::size_t _indent, std::string& _remainder, std::size_t _pos) {
4972 lines.push_back(std::string(_indent, ' ') + _remainder.substr(0, _pos));
4973 _remainder = _remainder.substr(_pos);
4974 }
4975
4976 typedef std::vector<std::string>::const_iterator const_iterator;
4977
begin() const4978 const_iterator begin() const { return lines.begin(); }
end() const4979 const_iterator end() const { return lines.end(); }
last() const4980 std::string const& last() const { return lines.back(); }
size() const4981 std::size_t size() const { return lines.size(); }
operator [](std::size_t _index) const4982 std::string const& operator[](std::size_t _index) const { return lines[_index]; }
toString() const4983 std::string toString() const {
4984 std::ostringstream oss;
4985 oss << *this;
4986 return oss.str();
4987 }
4988
operator <<(std::ostream & _stream,Text const & _text)4989 inline friend std::ostream& operator << (std::ostream& _stream, Text const& _text) {
4990 for (Text::const_iterator it = _text.begin(), itEnd = _text.end();
4991 it != itEnd; ++it) {
4992 if (it != _text.begin())
4993 _stream << "\n";
4994 _stream << *it;
4995 }
4996 return _stream;
4997 }
4998
4999 private:
5000 std::string str;
5001 TextAttributes attr;
5002 std::vector<std::string> lines;
5003 };
5004
5005 } // end namespace Tbc
5006
5007 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5008 } // end outer namespace
5009 #endif
5010
5011 #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5012 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5013
5014 namespace Catch {
5015 using Tbc::Text;
5016 using Tbc::TextAttributes;
5017 }
5018
5019 // #included from: catch_console_colour.hpp
5020 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
5021
5022 namespace Catch {
5023
5024 struct Colour {
5025 enum Code {
5026 None = 0,
5027
5028 White,
5029 Red,
5030 Green,
5031 Blue,
5032 Cyan,
5033 Yellow,
5034 Grey,
5035
5036 Bright = 0x10,
5037
5038 BrightRed = Bright | Red,
5039 BrightGreen = Bright | Green,
5040 LightGrey = Bright | Grey,
5041 BrightWhite = Bright | White,
5042
5043 // By intention
5044 FileName = LightGrey,
5045 Warning = Yellow,
5046 ResultError = BrightRed,
5047 ResultSuccess = BrightGreen,
5048 ResultExpectedFailure = Warning,
5049
5050 Error = BrightRed,
5051 Success = Green,
5052
5053 OriginalExpression = Cyan,
5054 ReconstructedExpression = Yellow,
5055
5056 SecondaryText = LightGrey,
5057 Headers = White
5058 };
5059
5060 // Use constructed object for RAII guard
5061 Colour(Code _colourCode);
5062 Colour(Colour const& other);
5063 ~Colour();
5064
5065 // Use static method for one-shot changes
5066 static void use(Code _colourCode);
5067
5068 private:
5069 bool m_moved;
5070 };
5071
operator <<(std::ostream & os,Colour const &)5072 inline std::ostream& operator << (std::ostream& os, Colour const&) { return os; }
5073
5074 } // end namespace Catch
5075
5076 // #included from: catch_interfaces_reporter.h
5077 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
5078
5079 #include <string>
5080 #include <ostream>
5081 #include <map>
5082 #include <assert.h>
5083
5084 namespace Catch
5085 {
5086 struct ReporterConfig {
ReporterConfigCatch::ReporterConfig5087 explicit ReporterConfig(Ptr<IConfig const> const& _fullConfig)
5088 : m_stream(&_fullConfig->stream()), m_fullConfig(_fullConfig) {}
5089
ReporterConfigCatch::ReporterConfig5090 ReporterConfig(Ptr<IConfig const> const& _fullConfig, std::ostream& _stream)
5091 : m_stream(&_stream), m_fullConfig(_fullConfig) {}
5092
streamCatch::ReporterConfig5093 std::ostream& stream() const { return *m_stream; }
fullConfigCatch::ReporterConfig5094 Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
5095
5096 private:
5097 std::ostream* m_stream;
5098 Ptr<IConfig const> m_fullConfig;
5099 };
5100
5101 struct ReporterPreferences {
ReporterPreferencesCatch::ReporterPreferences5102 ReporterPreferences()
5103 : shouldRedirectStdOut(false)
5104 {}
5105
5106 bool shouldRedirectStdOut;
5107 };
5108
5109 template<typename T>
5110 struct LazyStat : Option<T> {
LazyStatCatch::LazyStat5111 LazyStat() : used(false) {}
operator =Catch::LazyStat5112 LazyStat& operator=(T const& _value) {
5113 Option<T>::operator=(_value);
5114 used = false;
5115 return *this;
5116 }
resetCatch::LazyStat5117 void reset() {
5118 Option<T>::reset();
5119 used = false;
5120 }
5121 bool used;
5122 };
5123
5124 struct TestRunInfo {
TestRunInfoCatch::TestRunInfo5125 TestRunInfo(std::string const& _name) : name(_name) {}
5126 std::string name;
5127 };
5128 struct GroupInfo {
GroupInfoCatch::GroupInfo5129 GroupInfo(std::string const& _name,
5130 std::size_t _groupIndex,
5131 std::size_t _groupsCount)
5132 : name(_name),
5133 groupIndex(_groupIndex),
5134 groupsCounts(_groupsCount)
5135 {}
5136
5137 std::string name;
5138 std::size_t groupIndex;
5139 std::size_t groupsCounts;
5140 };
5141
5142 struct AssertionStats {
AssertionStatsCatch::AssertionStats5143 AssertionStats(AssertionResult const& _assertionResult,
5144 std::vector<MessageInfo> const& _infoMessages,
5145 Totals const& _totals)
5146 : assertionResult(_assertionResult),
5147 infoMessages(_infoMessages),
5148 totals(_totals)
5149 {
5150 if (assertionResult.hasMessage()) {
5151 // Copy message into messages list.
5152 // !TBD This should have been done earlier, somewhere
5153 MessageBuilder builder(assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType());
5154 builder << assertionResult.getMessage();
5155 builder.m_info.message = builder.m_stream.str();
5156
5157 infoMessages.push_back(builder.m_info);
5158 }
5159 }
5160 virtual ~AssertionStats();
5161
5162 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5163 AssertionStats(AssertionStats const&) = default;
5164 AssertionStats(AssertionStats &&) = default;
5165 AssertionStats& operator = (AssertionStats const&) = default;
5166 AssertionStats& operator = (AssertionStats &&) = default;
5167 # endif
5168
5169 AssertionResult assertionResult;
5170 std::vector<MessageInfo> infoMessages;
5171 Totals totals;
5172 };
5173
5174 struct SectionStats {
SectionStatsCatch::SectionStats5175 SectionStats(SectionInfo const& _sectionInfo,
5176 Counts const& _assertions,
5177 double _durationInSeconds,
5178 bool _missingAssertions)
5179 : sectionInfo(_sectionInfo),
5180 assertions(_assertions),
5181 durationInSeconds(_durationInSeconds),
5182 missingAssertions(_missingAssertions)
5183 {}
5184 virtual ~SectionStats();
5185 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5186 SectionStats(SectionStats const&) = default;
5187 SectionStats(SectionStats &&) = default;
5188 SectionStats& operator = (SectionStats const&) = default;
5189 SectionStats& operator = (SectionStats &&) = default;
5190 # endif
5191
5192 SectionInfo sectionInfo;
5193 Counts assertions;
5194 double durationInSeconds;
5195 bool missingAssertions;
5196 };
5197
5198 struct TestCaseStats {
TestCaseStatsCatch::TestCaseStats5199 TestCaseStats(TestCaseInfo const& _testInfo,
5200 Totals const& _totals,
5201 std::string const& _stdOut,
5202 std::string const& _stdErr,
5203 bool _aborting)
5204 : testInfo(_testInfo),
5205 totals(_totals),
5206 stdOut(_stdOut),
5207 stdErr(_stdErr),
5208 aborting(_aborting)
5209 {}
5210 virtual ~TestCaseStats();
5211
5212 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5213 TestCaseStats(TestCaseStats const&) = default;
5214 TestCaseStats(TestCaseStats &&) = default;
5215 TestCaseStats& operator = (TestCaseStats const&) = default;
5216 TestCaseStats& operator = (TestCaseStats &&) = default;
5217 # endif
5218
5219 TestCaseInfo testInfo;
5220 Totals totals;
5221 std::string stdOut;
5222 std::string stdErr;
5223 bool aborting;
5224 };
5225
5226 struct TestGroupStats {
TestGroupStatsCatch::TestGroupStats5227 TestGroupStats(GroupInfo const& _groupInfo,
5228 Totals const& _totals,
5229 bool _aborting)
5230 : groupInfo(_groupInfo),
5231 totals(_totals),
5232 aborting(_aborting)
5233 {}
TestGroupStatsCatch::TestGroupStats5234 TestGroupStats(GroupInfo const& _groupInfo)
5235 : groupInfo(_groupInfo),
5236 aborting(false)
5237 {}
5238 virtual ~TestGroupStats();
5239
5240 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5241 TestGroupStats(TestGroupStats const&) = default;
5242 TestGroupStats(TestGroupStats &&) = default;
5243 TestGroupStats& operator = (TestGroupStats const&) = default;
5244 TestGroupStats& operator = (TestGroupStats &&) = default;
5245 # endif
5246
5247 GroupInfo groupInfo;
5248 Totals totals;
5249 bool aborting;
5250 };
5251
5252 struct TestRunStats {
TestRunStatsCatch::TestRunStats5253 TestRunStats(TestRunInfo const& _runInfo,
5254 Totals const& _totals,
5255 bool _aborting)
5256 : runInfo(_runInfo),
5257 totals(_totals),
5258 aborting(_aborting)
5259 {}
5260 virtual ~TestRunStats();
5261
5262 # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestRunStatsCatch::TestRunStats5263 TestRunStats(TestRunStats const& _other)
5264 : runInfo(_other.runInfo),
5265 totals(_other.totals),
5266 aborting(_other.aborting)
5267 {}
5268 # else
5269 TestRunStats(TestRunStats const&) = default;
5270 TestRunStats(TestRunStats &&) = default;
5271 TestRunStats& operator = (TestRunStats const&) = default;
5272 TestRunStats& operator = (TestRunStats &&) = default;
5273 # endif
5274
5275 TestRunInfo runInfo;
5276 Totals totals;
5277 bool aborting;
5278 };
5279
5280 class MultipleReporters;
5281
5282 struct IStreamingReporter : IShared {
5283 virtual ~IStreamingReporter();
5284
5285 // Implementing class must also provide the following static method:
5286 // static std::string getDescription();
5287
5288 virtual ReporterPreferences getPreferences() const = 0;
5289
5290 virtual void noMatchingTestCases(std::string const& spec) = 0;
5291
5292 virtual void testRunStarting(TestRunInfo const& testRunInfo) = 0;
5293 virtual void testGroupStarting(GroupInfo const& groupInfo) = 0;
5294
5295 virtual void testCaseStarting(TestCaseInfo const& testInfo) = 0;
5296 virtual void sectionStarting(SectionInfo const& sectionInfo) = 0;
5297
5298 virtual void assertionStarting(AssertionInfo const& assertionInfo) = 0;
5299
5300 // The return value indicates if the messages buffer should be cleared:
5301 virtual bool assertionEnded(AssertionStats const& assertionStats) = 0;
5302
5303 virtual void sectionEnded(SectionStats const& sectionStats) = 0;
5304 virtual void testCaseEnded(TestCaseStats const& testCaseStats) = 0;
5305 virtual void testGroupEnded(TestGroupStats const& testGroupStats) = 0;
5306 virtual void testRunEnded(TestRunStats const& testRunStats) = 0;
5307
5308 virtual void skipTest(TestCaseInfo const& testInfo) = 0;
5309
tryAsMultiCatch::IStreamingReporter5310 virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
5311 };
5312
5313 struct IReporterFactory : IShared {
5314 virtual ~IReporterFactory();
5315 virtual IStreamingReporter* create(ReporterConfig const& config) const = 0;
5316 virtual std::string getDescription() const = 0;
5317 };
5318
5319 struct IReporterRegistry {
5320 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
5321 typedef std::vector<Ptr<IReporterFactory> > Listeners;
5322
5323 virtual ~IReporterRegistry();
5324 virtual IStreamingReporter* create(std::string const& name, Ptr<IConfig const> const& config) const = 0;
5325 virtual FactoryMap const& getFactories() const = 0;
5326 virtual Listeners const& getListeners() const = 0;
5327 };
5328
5329 Ptr<IStreamingReporter> addReporter(Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter);
5330
5331 }
5332
5333 #include <limits>
5334 #include <algorithm>
5335
5336 namespace Catch {
5337
listTests(Config const & config)5338 inline std::size_t listTests(Config const& config) {
5339
5340 TestSpec testSpec = config.testSpec();
5341 if (config.testSpec().hasFilters())
5342 Catch::cout() << "Matching test cases:\n";
5343 else {
5344 Catch::cout() << "All available test cases:\n";
5345 testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("*").testSpec();
5346 }
5347
5348 std::size_t matchedTests = 0;
5349 TextAttributes nameAttr, tagsAttr;
5350 nameAttr.setInitialIndent(2).setIndent(4);
5351 tagsAttr.setIndent(6);
5352
5353 std::vector<TestCase> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
5354 for (std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5355 it != itEnd;
5356 ++it) {
5357 matchedTests++;
5358 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5359 Colour::Code colour = testCaseInfo.isHidden()
5360 ? Colour::SecondaryText
5361 : Colour::None;
5362 Colour colourGuard(colour);
5363
5364 Catch::cout() << Text(testCaseInfo.name, nameAttr) << std::endl;
5365 if (!testCaseInfo.tags.empty())
5366 Catch::cout() << Text(testCaseInfo.tagsAsString, tagsAttr) << std::endl;
5367 }
5368
5369 if (!config.testSpec().hasFilters())
5370 Catch::cout() << pluralise(matchedTests, "test case") << "\n" << std::endl;
5371 else
5372 Catch::cout() << pluralise(matchedTests, "matching test case") << "\n" << std::endl;
5373 return matchedTests;
5374 }
5375
listTestsNamesOnly(Config const & config)5376 inline std::size_t listTestsNamesOnly(Config const& config) {
5377 TestSpec testSpec = config.testSpec();
5378 if (!config.testSpec().hasFilters())
5379 testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("*").testSpec();
5380 std::size_t matchedTests = 0;
5381 std::vector<TestCase> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
5382 for (std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5383 it != itEnd;
5384 ++it) {
5385 matchedTests++;
5386 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5387 Catch::cout() << testCaseInfo.name << std::endl;
5388 }
5389 return matchedTests;
5390 }
5391
5392 struct TagInfo {
TagInfoCatch::TagInfo5393 TagInfo() : count(0) {}
addCatch::TagInfo5394 void add(std::string const& spelling) {
5395 ++count;
5396 spellings.insert(spelling);
5397 }
allCatch::TagInfo5398 std::string all() const {
5399 std::string out;
5400 for (std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5401 it != itEnd;
5402 ++it)
5403 out += "[" + *it + "]";
5404 return out;
5405 }
5406 std::set<std::string> spellings;
5407 std::size_t count;
5408 };
5409
listTags(Config const & config)5410 inline std::size_t listTags(Config const& config) {
5411 TestSpec testSpec = config.testSpec();
5412 if (config.testSpec().hasFilters())
5413 Catch::cout() << "Tags for matching test cases:\n";
5414 else {
5415 Catch::cout() << "All available tags:\n";
5416 testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("*").testSpec();
5417 }
5418
5419 std::map<std::string, TagInfo> tagCounts;
5420
5421 std::vector<TestCase> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
5422 for (std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5423 it != itEnd;
5424 ++it) {
5425 for (std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5426 tagItEnd = it->getTestCaseInfo().tags.end();
5427 tagIt != tagItEnd;
5428 ++tagIt) {
5429 std::string tagName = *tagIt;
5430 std::string lcaseTagName = toLower(tagName);
5431 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find(lcaseTagName);
5432 if (countIt == tagCounts.end())
5433 countIt = tagCounts.insert(std::make_pair(lcaseTagName, TagInfo())).first;
5434 countIt->second.add(tagName);
5435 }
5436 }
5437
5438 for (std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5439 countItEnd = tagCounts.end();
5440 countIt != countItEnd;
5441 ++countIt) {
5442 std::ostringstream oss;
5443 oss << " " << std::setw(2) << countIt->second.count << " ";
5444 Text wrapper(countIt->second.all(), TextAttributes()
5445 .setInitialIndent(0)
5446 .setIndent(oss.str().size())
5447 .setWidth(CATCH_CONFIG_CONSOLE_WIDTH - 10));
5448 Catch::cout() << oss.str() << wrapper << "\n";
5449 }
5450 Catch::cout() << pluralise(tagCounts.size(), "tag") << "\n" << std::endl;
5451 return tagCounts.size();
5452 }
5453
listReporters(Config const &)5454 inline std::size_t listReporters(Config const& /*config*/) {
5455 Catch::cout() << "Available reporters:\n";
5456 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
5457 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
5458 std::size_t maxNameLen = 0;
5459 for (it = itBegin; it != itEnd; ++it)
5460 maxNameLen = (std::max)(maxNameLen, it->first.size());
5461
5462 for (it = itBegin; it != itEnd; ++it) {
5463 Text wrapper(it->second->getDescription(), TextAttributes()
5464 .setInitialIndent(0)
5465 .setIndent(7 + maxNameLen)
5466 .setWidth(CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8));
5467 Catch::cout() << " "
5468 << it->first
5469 << ":"
5470 << std::string(maxNameLen - it->first.size() + 2, ' ')
5471 << wrapper << "\n";
5472 }
5473 Catch::cout() << std::endl;
5474 return factories.size();
5475 }
5476
list(Config const & config)5477 inline Option<std::size_t> list(Config const& config) {
5478 Option<std::size_t> listedCount;
5479 if (config.listTests())
5480 listedCount = listedCount.valueOr(0) + listTests(config);
5481 if (config.listTestNamesOnly())
5482 listedCount = listedCount.valueOr(0) + listTestsNamesOnly(config);
5483 if (config.listTags())
5484 listedCount = listedCount.valueOr(0) + listTags(config);
5485 if (config.listReporters())
5486 listedCount = listedCount.valueOr(0) + listReporters(config);
5487 return listedCount;
5488 }
5489
5490 } // end namespace Catch
5491
5492 // #included from: internal/catch_run_context.hpp
5493 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
5494
5495 // #included from: catch_test_case_tracker.hpp
5496 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
5497
5498 #include <map>
5499 #include <string>
5500 #include <assert.h>
5501 #include <vector>
5502
5503 namespace Catch {
5504 namespace TestCaseTracking {
5505
5506 struct ITracker : SharedImpl<> {
5507 virtual ~ITracker();
5508
5509 // static queries
5510 virtual std::string name() const = 0;
5511
5512 // dynamic queries
5513 virtual bool isComplete() const = 0; // Successfully completed or failed
5514 virtual bool isSuccessfullyCompleted() const = 0;
5515 virtual bool isOpen() const = 0; // Started but not complete
5516 virtual bool hasChildren() const = 0;
5517
5518 virtual ITracker& parent() = 0;
5519
5520 // actions
5521 virtual void close() = 0; // Successfully complete
5522 virtual void fail() = 0;
5523 virtual void markAsNeedingAnotherRun() = 0;
5524
5525 virtual void addChild(Ptr<ITracker> const& child) = 0;
5526 virtual ITracker* findChild(std::string const& name) = 0;
5527 virtual void openChild() = 0;
5528
5529 // Debug/ checking
5530 virtual bool isSectionTracker() const = 0;
5531 virtual bool isIndexTracker() const = 0;
5532 };
5533
5534 class TrackerContext {
5535
5536 enum RunState {
5537 NotStarted,
5538 Executing,
5539 CompletedCycle
5540 };
5541
5542 Ptr<ITracker> m_rootTracker;
5543 ITracker* m_currentTracker;
5544 RunState m_runState;
5545
5546 public:
5547
instance()5548 static TrackerContext& instance() {
5549 static TrackerContext s_instance;
5550 return s_instance;
5551 }
5552
TrackerContext()5553 TrackerContext()
5554 : m_currentTracker(CATCH_NULL),
5555 m_runState(NotStarted)
5556 {}
5557
5558 ITracker& startRun();
5559
endRun()5560 void endRun() {
5561 m_rootTracker.reset();
5562 m_currentTracker = CATCH_NULL;
5563 m_runState = NotStarted;
5564 }
5565
startCycle()5566 void startCycle() {
5567 m_currentTracker = m_rootTracker.get();
5568 m_runState = Executing;
5569 }
completeCycle()5570 void completeCycle() {
5571 m_runState = CompletedCycle;
5572 }
5573
completedCycle() const5574 bool completedCycle() const {
5575 return m_runState == CompletedCycle;
5576 }
currentTracker()5577 ITracker& currentTracker() {
5578 return *m_currentTracker;
5579 }
setCurrentTracker(ITracker * tracker)5580 void setCurrentTracker(ITracker* tracker) {
5581 m_currentTracker = tracker;
5582 }
5583 };
5584
5585 class TrackerBase : public ITracker {
5586 protected:
5587 enum CycleState {
5588 NotStarted,
5589 Executing,
5590 ExecutingChildren,
5591 NeedsAnotherRun,
5592 CompletedSuccessfully,
5593 Failed
5594 };
5595 class TrackerHasName {
5596 std::string m_name;
5597 public:
TrackerHasName(std::string const & name)5598 TrackerHasName(std::string const& name) : m_name(name) {}
operator ()(Ptr<ITracker> const & tracker)5599 bool operator ()(Ptr<ITracker> const& tracker) {
5600 return tracker->name() == m_name;
5601 }
5602 };
5603 typedef std::vector<Ptr<ITracker> > Children;
5604 std::string m_name;
5605 TrackerContext& m_ctx;
5606 ITracker* m_parent;
5607 Children m_children;
5608 CycleState m_runState;
5609 public:
TrackerBase(std::string const & name,TrackerContext & ctx,ITracker * parent)5610 TrackerBase(std::string const& name, TrackerContext& ctx, ITracker* parent)
5611 : m_name(name),
5612 m_ctx(ctx),
5613 m_parent(parent),
5614 m_runState(NotStarted)
5615 {}
5616 virtual ~TrackerBase();
5617
name() const5618 virtual std::string name() const CATCH_OVERRIDE{
5619 return m_name;
5620 }
isComplete() const5621 virtual bool isComplete() const CATCH_OVERRIDE{
5622 return m_runState == CompletedSuccessfully || m_runState == Failed;
5623 }
isSuccessfullyCompleted() const5624 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE{
5625 return m_runState == CompletedSuccessfully;
5626 }
isOpen() const5627 virtual bool isOpen() const CATCH_OVERRIDE{
5628 return m_runState != NotStarted && !isComplete();
5629 }
hasChildren() const5630 virtual bool hasChildren() const CATCH_OVERRIDE{
5631 return !m_children.empty();
5632 }
5633
addChild(Ptr<ITracker> const & child)5634 virtual void addChild(Ptr<ITracker> const& child) CATCH_OVERRIDE{
5635 m_children.push_back(child);
5636 }
5637
findChild(std::string const & name)5638 virtual ITracker* findChild(std::string const& name) CATCH_OVERRIDE{
5639 Children::const_iterator it = std::find_if(m_children.begin(), m_children.end(), TrackerHasName(name));
5640 return(it != m_children.end())
5641 ? it->get()
5642 : CATCH_NULL;
5643 }
parent()5644 virtual ITracker& parent() CATCH_OVERRIDE{
5645 assert(m_parent); // Should always be non-null except for root
5646 return *m_parent;
5647 }
5648
openChild()5649 virtual void openChild() CATCH_OVERRIDE{
5650 if (m_runState != ExecutingChildren) {
5651 m_runState = ExecutingChildren;
5652 if (m_parent)
5653 m_parent->openChild();
5654 }
5655 }
5656
isSectionTracker() const5657 virtual bool isSectionTracker() const CATCH_OVERRIDE{ return false; }
isIndexTracker() const5658 virtual bool isIndexTracker() const CATCH_OVERRIDE{ return false; }
5659
open()5660 void open() {
5661 m_runState = Executing;
5662 moveToThis();
5663 if (m_parent)
5664 m_parent->openChild();
5665 }
5666
close()5667 virtual void close() CATCH_OVERRIDE{
5668
5669 // Close any still open children (e.g. generators)
5670 while (&m_ctx.currentTracker() != this)
5671 m_ctx.currentTracker().close();
5672
5673 switch (m_runState) {
5674 case NotStarted:
5675 case CompletedSuccessfully:
5676 case Failed:
5677 throw std::logic_error("Illogical state");
5678
5679 case NeedsAnotherRun:
5680 break;;
5681
5682 case Executing:
5683 m_runState = CompletedSuccessfully;
5684 break;
5685 case ExecutingChildren:
5686 if (m_children.empty() || m_children.back()->isComplete())
5687 m_runState = CompletedSuccessfully;
5688 break;
5689
5690 default:
5691 throw std::logic_error("Unexpected state");
5692 }
5693 moveToParent();
5694 m_ctx.completeCycle();
5695 }
fail()5696 virtual void fail() CATCH_OVERRIDE{
5697 m_runState = Failed;
5698 if (m_parent)
5699 m_parent->markAsNeedingAnotherRun();
5700 moveToParent();
5701 m_ctx.completeCycle();
5702 }
markAsNeedingAnotherRun()5703 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE{
5704 m_runState = NeedsAnotherRun;
5705 }
5706 private:
moveToParent()5707 void moveToParent() {
5708 assert(m_parent);
5709 m_ctx.setCurrentTracker(m_parent);
5710 }
moveToThis()5711 void moveToThis() {
5712 m_ctx.setCurrentTracker(this);
5713 }
5714 };
5715
5716 class SectionTracker : public TrackerBase {
5717 public:
SectionTracker(std::string const & name,TrackerContext & ctx,ITracker * parent)5718 SectionTracker(std::string const& name, TrackerContext& ctx, ITracker* parent)
5719 : TrackerBase(name, ctx, parent)
5720 {}
5721 virtual ~SectionTracker();
5722
isSectionTracker() const5723 virtual bool isSectionTracker() const CATCH_OVERRIDE{ return true; }
5724
acquire(TrackerContext & ctx,std::string const & name)5725 static SectionTracker& acquire(TrackerContext& ctx, std::string const& name) {
5726 SectionTracker* section = CATCH_NULL;
5727
5728 ITracker& currentTracker = ctx.currentTracker();
5729 if (ITracker* childTracker = currentTracker.findChild(name)) {
5730 assert(childTracker);
5731 assert(childTracker->isSectionTracker());
5732 section = static_cast<SectionTracker*>(childTracker);
5733 }
5734 else {
5735 section = new SectionTracker(name, ctx, ¤tTracker);
5736 currentTracker.addChild(section);
5737 }
5738 if (!ctx.completedCycle() && !section->isComplete()) {
5739
5740 section->open();
5741 }
5742 return *section;
5743 }
5744 };
5745
5746 class IndexTracker : public TrackerBase {
5747 int m_size;
5748 int m_index;
5749 public:
IndexTracker(std::string const & name,TrackerContext & ctx,ITracker * parent,int size)5750 IndexTracker(std::string const& name, TrackerContext& ctx, ITracker* parent, int size)
5751 : TrackerBase(name, ctx, parent),
5752 m_size(size),
5753 m_index(-1)
5754 {}
5755 virtual ~IndexTracker();
5756
isIndexTracker() const5757 virtual bool isIndexTracker() const CATCH_OVERRIDE{ return true; }
5758
acquire(TrackerContext & ctx,std::string const & name,int size)5759 static IndexTracker& acquire(TrackerContext& ctx, std::string const& name, int size) {
5760 IndexTracker* tracker = CATCH_NULL;
5761
5762 ITracker& currentTracker = ctx.currentTracker();
5763 if (ITracker* childTracker = currentTracker.findChild(name)) {
5764 assert(childTracker);
5765 assert(childTracker->isIndexTracker());
5766 tracker = static_cast<IndexTracker*>(childTracker);
5767 }
5768 else {
5769 tracker = new IndexTracker(name, ctx, ¤tTracker, size);
5770 currentTracker.addChild(tracker);
5771 }
5772
5773 if (!ctx.completedCycle() && !tracker->isComplete()) {
5774 if (tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun)
5775 tracker->moveNext();
5776 tracker->open();
5777 }
5778
5779 return *tracker;
5780 }
5781
index() const5782 int index() const { return m_index; }
5783
moveNext()5784 void moveNext() {
5785 m_index++;
5786 m_children.clear();
5787 }
5788
close()5789 virtual void close() CATCH_OVERRIDE{
5790 TrackerBase::close();
5791 if (m_runState == CompletedSuccessfully && m_index < m_size - 1)
5792 m_runState = Executing;
5793 }
5794 };
5795
startRun()5796 inline ITracker& TrackerContext::startRun() {
5797 m_rootTracker = new SectionTracker("{root}", *this, CATCH_NULL);
5798 m_currentTracker = CATCH_NULL;
5799 m_runState = Executing;
5800 return *m_rootTracker;
5801 }
5802
5803 } // namespace TestCaseTracking
5804
5805 using TestCaseTracking::ITracker;
5806 using TestCaseTracking::TrackerContext;
5807 using TestCaseTracking::SectionTracker;
5808 using TestCaseTracking::IndexTracker;
5809
5810 } // namespace Catch
5811
5812 // #included from: catch_fatal_condition.hpp
5813 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
5814
5815 namespace Catch {
5816
5817 // Report the error condition then exit the process
fatal(std::string const & message,int exitCode)5818 inline void fatal(std::string const& message, int exitCode) {
5819 IContext& context = Catch::getCurrentContext();
5820 IResultCapture* resultCapture = context.getResultCapture();
5821 resultCapture->handleFatalErrorCondition(message);
5822
5823 if (Catch::alwaysTrue()) // avoids "no return" warnings
5824 exit(exitCode);
5825 }
5826
5827 } // namespace Catch
5828
5829 #if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
5830
5831 namespace Catch {
5832
5833 struct FatalConditionHandler {
resetCatch::FatalConditionHandler5834 void reset() {}
5835 };
5836
5837 } // namespace Catch
5838
5839 #else // Not Windows - assumed to be POSIX compatible //////////////////////////
5840
5841 #include <signal.h>
5842
5843 namespace Catch {
5844
5845 struct SignalDefs { int id; const char* name; };
5846 extern SignalDefs signalDefs[];
5847 SignalDefs signalDefs[] = {
5848 { SIGINT, "SIGINT - Terminal interrupt signal" },
5849 { SIGILL, "SIGILL - Illegal instruction signal" },
5850 { SIGFPE, "SIGFPE - Floating point error signal" },
5851 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
5852 { SIGTERM, "SIGTERM - Termination request signal" },
5853 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
5854 };
5855
5856 struct FatalConditionHandler {
5857
handleSignalCatch::FatalConditionHandler5858 static void handleSignal(int sig) {
5859 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i)
5860 if (sig == signalDefs[i].id)
5861 fatal(signalDefs[i].name, -sig);
5862 fatal("<unknown signal>", -sig);
5863 }
5864
FatalConditionHandlerCatch::FatalConditionHandler5865 FatalConditionHandler() : m_isSet(true) {
5866 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i)
5867 signal(signalDefs[i].id, handleSignal);
5868 }
~FatalConditionHandlerCatch::FatalConditionHandler5869 ~FatalConditionHandler() {
5870 reset();
5871 }
resetCatch::FatalConditionHandler5872 void reset() {
5873 if (m_isSet) {
5874 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i)
5875 signal(signalDefs[i].id, SIG_DFL);
5876 m_isSet = false;
5877 }
5878 }
5879
5880 bool m_isSet;
5881 };
5882
5883 } // namespace Catch
5884
5885 #endif // not Windows
5886
5887 #include <set>
5888 #include <string>
5889
5890 namespace Catch {
5891
5892 class StreamRedirect {
5893
5894 public:
StreamRedirect(std::ostream & stream,std::string & targetString)5895 StreamRedirect(std::ostream& stream, std::string& targetString)
5896 : m_stream(stream),
5897 m_prevBuf(stream.rdbuf()),
5898 m_targetString(targetString)
5899 {
5900 stream.rdbuf(m_oss.rdbuf());
5901 }
5902
~StreamRedirect()5903 ~StreamRedirect() {
5904 m_targetString += m_oss.str();
5905 m_stream.rdbuf(m_prevBuf);
5906 }
5907
5908 private:
5909 std::ostream& m_stream;
5910 std::streambuf* m_prevBuf;
5911 std::ostringstream m_oss;
5912 std::string& m_targetString;
5913 };
5914
5915 ///////////////////////////////////////////////////////////////////////////
5916
5917 class RunContext : public IResultCapture, public IRunner {
5918
5919 RunContext(RunContext const&);
5920 void operator =(RunContext const&);
5921
5922 public:
5923
RunContext(Ptr<IConfig const> const & _config,Ptr<IStreamingReporter> const & reporter)5924 explicit RunContext(Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter)
5925 : m_runInfo(_config->name()),
5926 m_context(getCurrentMutableContext()),
5927 m_activeTestCase(CATCH_NULL),
5928 m_config(_config),
5929 m_reporter(reporter)
5930 {
5931 m_context.setRunner(this);
5932 m_context.setConfig(m_config);
5933 m_context.setResultCapture(this);
5934 m_reporter->testRunStarting(m_runInfo);
5935 }
5936
~RunContext()5937 virtual ~RunContext() {
5938 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
5939 }
5940
testGroupStarting(std::string const & testSpec,std::size_t groupIndex,std::size_t groupsCount)5941 void testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {
5942 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
5943 }
testGroupEnded(std::string const & testSpec,Totals const & totals,std::size_t groupIndex,std::size_t groupsCount)5944 void testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) {
5945 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
5946 }
5947
runTest(TestCase const & testCase)5948 Totals runTest(TestCase const& testCase) {
5949 Totals prevTotals = m_totals;
5950
5951 std::string redirectedCout;
5952 std::string redirectedCerr;
5953
5954 TestCaseInfo testInfo = testCase.getTestCaseInfo();
5955
5956 m_reporter->testCaseStarting(testInfo);
5957
5958 m_activeTestCase = &testCase;
5959
5960 do {
5961 m_trackerContext.startRun();
5962 do {
5963 m_trackerContext.startCycle();
5964 m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, testInfo.name);
5965 runCurrentTest(redirectedCout, redirectedCerr);
5966 } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
5967 }
5968 // !TBD: deprecated - this will be replaced by indexed trackers
5969 while (getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting());
5970
5971 Totals deltaTotals = m_totals.delta(prevTotals);
5972 if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
5973 deltaTotals.assertions.failed++;
5974 deltaTotals.testCases.passed--;
5975 deltaTotals.testCases.failed++;
5976 }
5977 m_totals.testCases += deltaTotals.testCases;
5978 m_reporter->testCaseEnded(TestCaseStats(testInfo,
5979 deltaTotals,
5980 redirectedCout,
5981 redirectedCerr,
5982 aborting()));
5983
5984 m_activeTestCase = CATCH_NULL;
5985 m_testCaseTracker = CATCH_NULL;
5986
5987 return deltaTotals;
5988 }
5989
config() const5990 Ptr<IConfig const> config() const {
5991 return m_config;
5992 }
5993
5994 private: // IResultCapture
5995
assertionEnded(AssertionResult const & result)5996 virtual void assertionEnded(AssertionResult const& result) {
5997 if (result.getResultType() == ResultWas::Ok) {
5998 m_totals.assertions.passed++;
5999 }
6000 else if (!result.isOk()) {
6001 m_totals.assertions.failed++;
6002 }
6003
6004 if (m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)))
6005 m_messages.clear();
6006
6007 // Reset working state
6008 m_lastAssertionInfo = AssertionInfo("", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}", m_lastAssertionInfo.resultDisposition);
6009 m_lastResult = result;
6010 }
6011
sectionStarted(SectionInfo const & sectionInfo,Counts & assertions)6012 virtual bool sectionStarted(
6013 SectionInfo const& sectionInfo,
6014 Counts& assertions
6015 )
6016 {
6017 std::ostringstream oss;
6018 oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
6019
6020 ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, oss.str());
6021 if (!sectionTracker.isOpen())
6022 return false;
6023 m_activeSections.push_back(§ionTracker);
6024
6025 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
6026
6027 m_reporter->sectionStarting(sectionInfo);
6028
6029 assertions = m_totals.assertions;
6030
6031 return true;
6032 }
testForMissingAssertions(Counts & assertions)6033 bool testForMissingAssertions(Counts& assertions) {
6034 if (assertions.total() != 0)
6035 return false;
6036 if (!m_config->warnAboutMissingAssertions())
6037 return false;
6038 if (m_trackerContext.currentTracker().hasChildren())
6039 return false;
6040 m_totals.assertions.failed++;
6041 assertions.failed++;
6042 return true;
6043 }
6044
sectionEnded(SectionEndInfo const & endInfo)6045 virtual void sectionEnded(SectionEndInfo const& endInfo) {
6046 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
6047 bool missingAssertions = testForMissingAssertions(assertions);
6048
6049 if (!m_activeSections.empty()) {
6050 m_activeSections.back()->close();
6051 m_activeSections.pop_back();
6052 }
6053
6054 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
6055 m_messages.clear();
6056 }
6057
sectionEndedEarly(SectionEndInfo const & endInfo)6058 virtual void sectionEndedEarly(SectionEndInfo const& endInfo) {
6059 if (m_unfinishedSections.empty())
6060 m_activeSections.back()->fail();
6061 else
6062 m_activeSections.back()->close();
6063 m_activeSections.pop_back();
6064
6065 m_unfinishedSections.push_back(endInfo);
6066 }
6067
pushScopedMessage(MessageInfo const & message)6068 virtual void pushScopedMessage(MessageInfo const& message) {
6069 m_messages.push_back(message);
6070 }
6071
popScopedMessage(MessageInfo const & message)6072 virtual void popScopedMessage(MessageInfo const& message) {
6073 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
6074 }
6075
getCurrentTestName() const6076 virtual std::string getCurrentTestName() const {
6077 return m_activeTestCase
6078 ? m_activeTestCase->getTestCaseInfo().name
6079 : "";
6080 }
6081
getLastResult() const6082 virtual const AssertionResult* getLastResult() const {
6083 return &m_lastResult;
6084 }
6085
handleFatalErrorCondition(std::string const & message)6086 virtual void handleFatalErrorCondition(std::string const& message) {
6087 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
6088 resultBuilder.setResultType(ResultWas::FatalErrorCondition);
6089 resultBuilder << message;
6090 resultBuilder.captureExpression();
6091
6092 handleUnfinishedSections();
6093
6094 // Recreate section for test case (as we will lose the one that was in scope)
6095 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6096 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
6097
6098 Counts assertions;
6099 assertions.failed = 1;
6100 SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
6101 m_reporter->sectionEnded(testCaseSectionStats);
6102
6103 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
6104
6105 Totals deltaTotals;
6106 deltaTotals.testCases.failed = 1;
6107 m_reporter->testCaseEnded(TestCaseStats(testInfo,
6108 deltaTotals,
6109 "",
6110 "",
6111 false));
6112 m_totals.testCases.failed++;
6113 testGroupEnded("", m_totals, 1, 1);
6114 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
6115 }
6116
6117 public:
6118 // !TBD We need to do this another way!
aborting() const6119 bool aborting() const {
6120 return m_totals.assertions.failed == static_cast<std::size_t>(m_config->abortAfter());
6121 }
6122
6123 private:
6124
runCurrentTest(std::string & redirectedCout,std::string & redirectedCerr)6125 void runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr) {
6126 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6127 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
6128 m_reporter->sectionStarting(testCaseSection);
6129 Counts prevAssertions = m_totals.assertions;
6130 double duration = 0;
6131 try {
6132 m_lastAssertionInfo = AssertionInfo("TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal);
6133
6134 seedRng(*m_config);
6135
6136 Timer timer;
6137 timer.start();
6138 if (m_reporter->getPreferences().shouldRedirectStdOut) {
6139 StreamRedirect coutRedir(Catch::cout(), redirectedCout);
6140 StreamRedirect cerrRedir(Catch::cerr(), redirectedCerr);
6141 invokeActiveTestCase();
6142 }
6143 else {
6144 invokeActiveTestCase();
6145 }
6146 duration = timer.getElapsedSeconds();
6147 }
6148 catch (TestFailureException&) {
6149 // This just means the test was aborted due to failure
6150 }
6151 catch (...) {
6152 makeUnexpectedResultBuilder().useActiveException();
6153 }
6154 m_testCaseTracker->close();
6155 handleUnfinishedSections();
6156 m_messages.clear();
6157
6158 Counts assertions = m_totals.assertions - prevAssertions;
6159 bool missingAssertions = testForMissingAssertions(assertions);
6160
6161 if (testCaseInfo.okToFail()) {
6162 std::swap(assertions.failedButOk, assertions.failed);
6163 m_totals.assertions.failed -= assertions.failedButOk;
6164 m_totals.assertions.failedButOk += assertions.failedButOk;
6165 }
6166
6167 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
6168 m_reporter->sectionEnded(testCaseSectionStats);
6169 }
6170
invokeActiveTestCase()6171 void invokeActiveTestCase() {
6172 FatalConditionHandler fatalConditionHandler; // Handle signals
6173 m_activeTestCase->invoke();
6174 fatalConditionHandler.reset();
6175 }
6176
6177 private:
6178
makeUnexpectedResultBuilder() const6179 ResultBuilder makeUnexpectedResultBuilder() const {
6180 return ResultBuilder(m_lastAssertionInfo.macroName.c_str(),
6181 m_lastAssertionInfo.lineInfo,
6182 m_lastAssertionInfo.capturedExpression.c_str(),
6183 m_lastAssertionInfo.resultDisposition);
6184 }
6185
handleUnfinishedSections()6186 void handleUnfinishedSections() {
6187 // If sections ended prematurely due to an exception we stored their
6188 // infos here so we can tear them down outside the unwind process.
6189 for (std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
6190 itEnd = m_unfinishedSections.rend();
6191 it != itEnd;
6192 ++it)
6193 sectionEnded(*it);
6194 m_unfinishedSections.clear();
6195 }
6196
6197 TestRunInfo m_runInfo;
6198 IMutableContext& m_context;
6199 TestCase const* m_activeTestCase;
6200 ITracker* m_testCaseTracker;
6201 ITracker* m_currentSectionTracker;
6202 AssertionResult m_lastResult;
6203
6204 Ptr<IConfig const> m_config;
6205 Totals m_totals;
6206 Ptr<IStreamingReporter> m_reporter;
6207 std::vector<MessageInfo> m_messages;
6208 AssertionInfo m_lastAssertionInfo;
6209 std::vector<SectionEndInfo> m_unfinishedSections;
6210 std::vector<ITracker*> m_activeSections;
6211 TrackerContext m_trackerContext;
6212 };
6213
getResultCapture()6214 IResultCapture& getResultCapture() {
6215 if (IResultCapture* capture = getCurrentContext().getResultCapture())
6216 return *capture;
6217 else
6218 throw std::logic_error("No result capture instance");
6219 }
6220
6221 } // end namespace Catch
6222
6223 // #included from: internal/catch_version.h
6224 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
6225
6226 namespace Catch {
6227
6228 // Versioning information
6229 struct Version {
6230 Version(unsigned int _majorVersion,
6231 unsigned int _minorVersion,
6232 unsigned int _patchNumber,
6233 std::string const& _branchName,
6234 unsigned int _buildNumber);
6235
6236 unsigned int const majorVersion;
6237 unsigned int const minorVersion;
6238 unsigned int const patchNumber;
6239
6240 // buildNumber is only used if branchName is not null
6241 std::string const branchName;
6242 unsigned int const buildNumber;
6243
6244 friend std::ostream& operator << (std::ostream& os, Version const& version);
6245
6246 private:
6247 void operator=(Version const&);
6248 };
6249
6250 extern Version libraryVersion;
6251 }
6252
6253 #include <fstream>
6254 #include <stdlib.h>
6255 #include <limits>
6256
6257 namespace Catch {
6258
createReporter(std::string const & reporterName,Ptr<Config> const & config)6259 Ptr<IStreamingReporter> createReporter(std::string const& reporterName, Ptr<Config> const& config) {
6260 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create(reporterName, config.get());
6261 if (!reporter) {
6262 std::ostringstream oss;
6263 oss << "No reporter registered with name: '" << reporterName << "'";
6264 throw std::domain_error(oss.str());
6265 }
6266 return reporter;
6267 }
6268
makeReporter(Ptr<Config> const & config)6269 Ptr<IStreamingReporter> makeReporter(Ptr<Config> const& config) {
6270 std::vector<std::string> reporters = config->getReporterNames();
6271 if (reporters.empty())
6272 reporters.push_back("console");
6273
6274 Ptr<IStreamingReporter> reporter;
6275 for (std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
6276 it != itEnd;
6277 ++it)
6278 reporter = addReporter(reporter, createReporter(*it, config));
6279 return reporter;
6280 }
addListeners(Ptr<IConfig const> const & config,Ptr<IStreamingReporter> reporters)6281 Ptr<IStreamingReporter> addListeners(Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters) {
6282 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
6283 for (IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
6284 it != itEnd;
6285 ++it)
6286 reporters = addReporter(reporters, (*it)->create(ReporterConfig(config)));
6287 return reporters;
6288 }
6289
runTests(Ptr<Config> const & config)6290 Totals runTests(Ptr<Config> const& config) {
6291
6292 Ptr<IConfig const> iconfig = config.get();
6293
6294 Ptr<IStreamingReporter> reporter = makeReporter(config);
6295 reporter = addListeners(iconfig, reporter);
6296
6297 RunContext context(iconfig, reporter);
6298
6299 Totals totals;
6300
6301 context.testGroupStarting(config->name(), 1, 1);
6302
6303 TestSpec testSpec = config->testSpec();
6304 if (!testSpec.hasFilters())
6305 testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests
6306
6307 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted(*iconfig);
6308 for (std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
6309 it != itEnd;
6310 ++it) {
6311 if (!context.aborting() && matchTest(*it, testSpec, *iconfig))
6312 totals += context.runTest(*it);
6313 else
6314 reporter->skipTest(*it);
6315 }
6316
6317 context.testGroupEnded(iconfig->name(), totals, 1, 1);
6318 return totals;
6319 }
6320
applyFilenamesAsTags(IConfig const & config)6321 void applyFilenamesAsTags(IConfig const& config) {
6322 std::vector<TestCase> const& tests = getAllTestCasesSorted(config);
6323 for (std::size_t i = 0; i < tests.size(); ++i) {
6324 TestCase& test = const_cast<TestCase&>(tests[i]);
6325 std::set<std::string> tags = test.tags;
6326
6327 std::string filename = test.lineInfo.file;
6328 std::string::size_type lastSlash = filename.find_last_of("\\/");
6329 if (lastSlash != std::string::npos)
6330 filename = filename.substr(lastSlash + 1);
6331
6332 std::string::size_type lastDot = filename.find_last_of(".");
6333 if (lastDot != std::string::npos)
6334 filename = filename.substr(0, lastDot);
6335
6336 tags.insert("#" + filename);
6337 setTags(test, tags);
6338 }
6339 }
6340
6341 class Session : NonCopyable {
6342 static bool alreadyInstantiated;
6343
6344 public:
6345
6346 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
6347
Session()6348 Session()
6349 : m_cli(makeCommandLineParser()) {
6350 if (alreadyInstantiated) {
6351 std::string msg = "Only one instance of Catch::Session can ever be used";
6352 Catch::cerr() << msg << std::endl;
6353 throw std::logic_error(msg);
6354 }
6355 alreadyInstantiated = true;
6356 }
~Session()6357 ~Session() {
6358 Catch::cleanUp();
6359 }
6360
showHelp(std::string const & processName)6361 void showHelp(std::string const& processName) {
6362 Catch::cout() << "\nCatch v" << libraryVersion << "\n";
6363
6364 m_cli.usage(Catch::cout(), processName);
6365 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
6366 }
6367
applyCommandLine(int argc,char const * const * const argv,OnUnusedOptions::DoWhat unusedOptionBehaviour=OnUnusedOptions::Fail)6368 int applyCommandLine(int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail) {
6369 try {
6370 m_cli.setThrowOnUnrecognisedTokens(unusedOptionBehaviour == OnUnusedOptions::Fail);
6371 m_unusedTokens = m_cli.parseInto(Clara::argsToVector(argc, argv), m_configData);
6372 if (m_configData.showHelp)
6373 showHelp(m_configData.processName);
6374 m_config.reset();
6375 }
6376 catch (std::exception& ex) {
6377 {
6378 Colour colourGuard(Colour::Red);
6379 Catch::cerr()
6380 << "\nError(s) in input:\n"
6381 << Text(ex.what(), TextAttributes().setIndent(2))
6382 << "\n\n";
6383 }
6384 m_cli.usage(Catch::cout(), m_configData.processName);
6385 return (std::numeric_limits<int>::max)();
6386 }
6387 return 0;
6388 }
6389
useConfigData(ConfigData const & _configData)6390 void useConfigData(ConfigData const& _configData) {
6391 m_configData = _configData;
6392 m_config.reset();
6393 }
6394
run(int argc,char const * const * const argv)6395 int run(int argc, char const* const* const argv) {
6396
6397 int returnCode = applyCommandLine(argc, argv);
6398 if (returnCode == 0)
6399 returnCode = run();
6400 return returnCode;
6401 }
6402
run()6403 int run() {
6404 if (m_configData.showHelp)
6405 return 0;
6406
6407 try
6408 {
6409 config(); // Force config to be constructed
6410
6411 seedRng(*m_config);
6412
6413 if (m_configData.filenamesAsTags)
6414 applyFilenamesAsTags(*m_config);
6415
6416 // Handle list request
6417 if (Option<std::size_t> listed = list(config()))
6418 return static_cast<int>(*listed);
6419
6420 return static_cast<int>(runTests(m_config).assertions.failed);
6421 }
6422 catch (std::exception& ex) {
6423 Catch::cerr() << ex.what() << std::endl;
6424 return (std::numeric_limits<int>::max)();
6425 }
6426 }
6427
cli() const6428 Clara::CommandLine<ConfigData> const& cli() const {
6429 return m_cli;
6430 }
unusedTokens() const6431 std::vector<Clara::Parser::Token> const& unusedTokens() const {
6432 return m_unusedTokens;
6433 }
configData()6434 ConfigData& configData() {
6435 return m_configData;
6436 }
config()6437 Config& config() {
6438 if (!m_config)
6439 m_config = new Config(m_configData);
6440 return *m_config;
6441 }
6442 private:
6443 Clara::CommandLine<ConfigData> m_cli;
6444 std::vector<Clara::Parser::Token> m_unusedTokens;
6445 ConfigData m_configData;
6446 Ptr<Config> m_config;
6447 };
6448
6449 bool Session::alreadyInstantiated = false;
6450
6451 } // end namespace Catch
6452
6453 // #included from: catch_registry_hub.hpp
6454 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
6455
6456 // #included from: catch_test_case_registry_impl.hpp
6457 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
6458
6459 #include <vector>
6460 #include <set>
6461 #include <sstream>
6462 #include <iostream>
6463 #include <algorithm>
6464
6465 #ifdef CATCH_CPP14_OR_GREATER
6466 #include <random>
6467 #endif
6468
6469 namespace Catch {
6470
6471 struct RandomNumberGenerator {
6472 typedef int result_type;
6473
operator ()Catch::RandomNumberGenerator6474 result_type operator()(result_type n) const { return std::rand() % n; }
6475
6476 #ifdef CATCH_CPP14_OR_GREATER
minCatch::RandomNumberGenerator6477 static constexpr result_type min() { return 0; }
maxCatch::RandomNumberGenerator6478 static constexpr result_type max() { return 1000000; }
operator ()Catch::RandomNumberGenerator6479 result_type operator()() const { return std::rand() % max(); }
6480 #endif
6481 template<typename V>
shuffleCatch::RandomNumberGenerator6482 static void shuffle(V& vector) {
6483 RandomNumberGenerator rng;
6484 #ifdef CATCH_CPP14_OR_GREATER
6485 std::shuffle(vector.begin(), vector.end(), rng);
6486 #else
6487 std::random_shuffle(vector.begin(), vector.end(), rng);
6488 #endif
6489 }
6490 };
6491
sortTests(IConfig const & config,std::vector<TestCase> const & unsortedTestCases)6492 inline std::vector<TestCase> sortTests(IConfig const& config, std::vector<TestCase> const& unsortedTestCases) {
6493
6494 std::vector<TestCase> sorted = unsortedTestCases;
6495
6496 switch (config.runOrder()) {
6497 case RunTests::InLexicographicalOrder:
6498 std::sort(sorted.begin(), sorted.end());
6499 break;
6500 case RunTests::InRandomOrder:
6501 {
6502 seedRng(config);
6503 RandomNumberGenerator::shuffle(sorted);
6504 }
6505 break;
6506 case RunTests::InDeclarationOrder:
6507 // already in declaration order
6508 break;
6509 }
6510 return sorted;
6511 }
matchTest(TestCase const & testCase,TestSpec const & testSpec,IConfig const & config)6512 bool matchTest(TestCase const& testCase, TestSpec const& testSpec, IConfig const& config) {
6513 return testSpec.matches(testCase) && (config.allowThrows() || !testCase.throws());
6514 }
6515
enforceNoDuplicateTestCases(std::vector<TestCase> const & functions)6516 void enforceNoDuplicateTestCases(std::vector<TestCase> const& functions) {
6517 std::set<TestCase> seenFunctions;
6518 for (std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
6519 it != itEnd;
6520 ++it) {
6521 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert(*it);
6522 if (!prev.second) {
6523 std::ostringstream ss;
6524
6525 ss << Colour(Colour::Red)
6526 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
6527 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
6528 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
6529
6530 throw std::runtime_error(ss.str());
6531 }
6532 }
6533 }
6534
filterTests(std::vector<TestCase> const & testCases,TestSpec const & testSpec,IConfig const & config)6535 std::vector<TestCase> filterTests(std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config) {
6536 std::vector<TestCase> filtered;
6537 filtered.reserve(testCases.size());
6538 for (std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
6539 it != itEnd;
6540 ++it)
6541 if (matchTest(*it, testSpec, config))
6542 filtered.push_back(*it);
6543 return filtered;
6544 }
getAllTestCasesSorted(IConfig const & config)6545 std::vector<TestCase> const& getAllTestCasesSorted(IConfig const& config) {
6546 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted(config);
6547 }
6548
6549 class TestRegistry : public ITestCaseRegistry {
6550 public:
TestRegistry()6551 TestRegistry()
6552 : m_currentSortOrder(RunTests::InDeclarationOrder),
6553 m_unnamedCount(0)
6554 {}
6555 virtual ~TestRegistry();
6556
registerTest(TestCase const & testCase)6557 virtual void registerTest(TestCase const& testCase) {
6558 std::string name = testCase.getTestCaseInfo().name;
6559 if (name == "") {
6560 std::ostringstream oss;
6561 oss << "Anonymous test case " << ++m_unnamedCount;
6562 return registerTest(testCase.withName(oss.str()));
6563 }
6564 m_functions.push_back(testCase);
6565 }
6566
getAllTests() const6567 virtual std::vector<TestCase> const& getAllTests() const {
6568 return m_functions;
6569 }
getAllTestsSorted(IConfig const & config) const6570 virtual std::vector<TestCase> const& getAllTestsSorted(IConfig const& config) const {
6571 if (m_sortedFunctions.empty())
6572 enforceNoDuplicateTestCases(m_functions);
6573
6574 if (m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty()) {
6575 m_sortedFunctions = sortTests(config, m_functions);
6576 m_currentSortOrder = config.runOrder();
6577 }
6578 return m_sortedFunctions;
6579 }
6580
6581 private:
6582 std::vector<TestCase> m_functions;
6583 mutable RunTests::InWhatOrder m_currentSortOrder;
6584 mutable std::vector<TestCase> m_sortedFunctions;
6585 size_t m_unnamedCount;
6586 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
6587 };
6588
6589 ///////////////////////////////////////////////////////////////////////////
6590
6591 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
6592 public:
6593
FreeFunctionTestCase(TestFunction fun)6594 FreeFunctionTestCase(TestFunction fun) : m_fun(fun) {}
6595
invoke() const6596 virtual void invoke() const {
6597 m_fun();
6598 }
6599
6600 private:
6601 virtual ~FreeFunctionTestCase();
6602
6603 TestFunction m_fun;
6604 };
6605
extractClassName(std::string const & classOrQualifiedMethodName)6606 inline std::string extractClassName(std::string const& classOrQualifiedMethodName) {
6607 std::string className = classOrQualifiedMethodName;
6608 if (startsWith(className, "&"))
6609 {
6610 std::size_t lastColons = className.rfind("::");
6611 std::size_t penultimateColons = className.rfind("::", lastColons - 1);
6612 if (penultimateColons == std::string::npos)
6613 penultimateColons = 1;
6614 className = className.substr(penultimateColons, lastColons - penultimateColons);
6615 }
6616 return className;
6617 }
6618
registerTestCase(ITestCase * testCase,char const * classOrQualifiedMethodName,NameAndDesc const & nameAndDesc,SourceLineInfo const & lineInfo)6619 void registerTestCase
6620 (ITestCase* testCase,
6621 char const* classOrQualifiedMethodName,
6622 NameAndDesc const& nameAndDesc,
6623 SourceLineInfo const& lineInfo) {
6624
6625 getMutableRegistryHub().registerTest
6626 (makeTestCase
6627 (testCase,
6628 extractClassName(classOrQualifiedMethodName),
6629 nameAndDesc.name,
6630 nameAndDesc.description,
6631 lineInfo));
6632 }
registerTestCaseFunction(TestFunction function,SourceLineInfo const & lineInfo,NameAndDesc const & nameAndDesc)6633 void registerTestCaseFunction
6634 (TestFunction function,
6635 SourceLineInfo const& lineInfo,
6636 NameAndDesc const& nameAndDesc) {
6637 registerTestCase(new FreeFunctionTestCase(function), "", nameAndDesc, lineInfo);
6638 }
6639
6640 ///////////////////////////////////////////////////////////////////////////
6641
AutoReg(TestFunction function,SourceLineInfo const & lineInfo,NameAndDesc const & nameAndDesc)6642 AutoReg::AutoReg
6643 (TestFunction function,
6644 SourceLineInfo const& lineInfo,
6645 NameAndDesc const& nameAndDesc) {
6646 registerTestCaseFunction(function, lineInfo, nameAndDesc);
6647 }
6648
~AutoReg()6649 AutoReg::~AutoReg() {}
6650
6651 } // end namespace Catch
6652
6653 // #included from: catch_reporter_registry.hpp
6654 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
6655
6656 #include <map>
6657
6658 namespace Catch {
6659
6660 class ReporterRegistry : public IReporterRegistry {
6661
6662 public:
6663
~ReporterRegistry()6664 virtual ~ReporterRegistry() CATCH_OVERRIDE{}
6665
create(std::string const & name,Ptr<IConfig const> const & config) const6666 virtual IStreamingReporter* create(std::string const& name, Ptr<IConfig const> const& config) const CATCH_OVERRIDE{
6667 FactoryMap::const_iterator it = m_factories.find(name);
6668 if (it == m_factories.end())
6669 return CATCH_NULL;
6670 return it->second->create(ReporterConfig(config));
6671 }
6672
registerReporter(std::string const & name,Ptr<IReporterFactory> const & factory)6673 void registerReporter(std::string const& name, Ptr<IReporterFactory> const& factory) {
6674 m_factories.insert(std::make_pair(name, factory));
6675 }
registerListener(Ptr<IReporterFactory> const & factory)6676 void registerListener(Ptr<IReporterFactory> const& factory) {
6677 m_listeners.push_back(factory);
6678 }
6679
getFactories() const6680 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE{
6681 return m_factories;
6682 }
getListeners() const6683 virtual Listeners const& getListeners() const CATCH_OVERRIDE{
6684 return m_listeners;
6685 }
6686
6687 private:
6688 FactoryMap m_factories;
6689 Listeners m_listeners;
6690 };
6691 }
6692
6693 // #included from: catch_exception_translator_registry.hpp
6694 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
6695
6696 #ifdef __OBJC__
6697 #import "Foundation/Foundation.h"
6698 #endif
6699
6700 namespace Catch {
6701
6702 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
6703 public:
~ExceptionTranslatorRegistry()6704 ~ExceptionTranslatorRegistry() {
6705 deleteAll(m_translators);
6706 }
6707
registerTranslator(const IExceptionTranslator * translator)6708 virtual void registerTranslator(const IExceptionTranslator* translator) {
6709 m_translators.push_back(translator);
6710 }
6711
translateActiveException() const6712 virtual std::string translateActiveException() const {
6713 try {
6714 #ifdef __OBJC__
6715 // In Objective-C try objective-c exceptions first
6716 @try {
6717 return tryTranslators();
6718 }
6719 @catch (NSException *exception) {
6720 return Catch::toString([exception description]);
6721 }
6722 #else
6723 return tryTranslators();
6724 #endif
6725 }
6726 catch (TestFailureException&) {
6727 throw;
6728 }
6729 catch (std::exception& ex) {
6730 return ex.what();
6731 }
6732 catch (std::string& msg) {
6733 return msg;
6734 }
6735 catch (const char* msg) {
6736 return msg;
6737 }
6738 catch (...) {
6739 return "Unknown exception";
6740 }
6741 }
6742
tryTranslators() const6743 std::string tryTranslators() const {
6744 if (m_translators.empty())
6745 throw;
6746 else
6747 return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
6748 }
6749
6750 private:
6751 std::vector<const IExceptionTranslator*> m_translators;
6752 };
6753 }
6754
6755 namespace Catch {
6756
6757 namespace {
6758
6759 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
6760
6761 RegistryHub(RegistryHub const&);
6762 void operator=(RegistryHub const&);
6763
6764 public: // IRegistryHub
RegistryHub()6765 RegistryHub() {
6766 }
getReporterRegistry() const6767 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE{
6768 return m_reporterRegistry;
6769 }
getTestCaseRegistry() const6770 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE{
6771 return m_testCaseRegistry;
6772 }
getExceptionTranslatorRegistry()6773 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE{
6774 return m_exceptionTranslatorRegistry;
6775 }
6776
6777 public: // IMutableRegistryHub
registerReporter(std::string const & name,Ptr<IReporterFactory> const & factory)6778 virtual void registerReporter(std::string const& name, Ptr<IReporterFactory> const& factory) CATCH_OVERRIDE{
6779 m_reporterRegistry.registerReporter(name, factory);
6780 }
registerListener(Ptr<IReporterFactory> const & factory)6781 virtual void registerListener(Ptr<IReporterFactory> const& factory) CATCH_OVERRIDE{
6782 m_reporterRegistry.registerListener(factory);
6783 }
registerTest(TestCase const & testInfo)6784 virtual void registerTest(TestCase const& testInfo) CATCH_OVERRIDE{
6785 m_testCaseRegistry.registerTest(testInfo);
6786 }
registerTranslator(const IExceptionTranslator * translator)6787 virtual void registerTranslator(const IExceptionTranslator* translator) CATCH_OVERRIDE{
6788 m_exceptionTranslatorRegistry.registerTranslator(translator);
6789 }
6790
6791 private:
6792 TestRegistry m_testCaseRegistry;
6793 ReporterRegistry m_reporterRegistry;
6794 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
6795 };
6796
6797 // Single, global, instance
getTheRegistryHub()6798 inline RegistryHub*& getTheRegistryHub() {
6799 static RegistryHub* theRegistryHub = CATCH_NULL;
6800 if (!theRegistryHub)
6801 theRegistryHub = new RegistryHub();
6802 return theRegistryHub;
6803 }
6804 }
6805
getRegistryHub()6806 IRegistryHub& getRegistryHub() {
6807 return *getTheRegistryHub();
6808 }
getMutableRegistryHub()6809 IMutableRegistryHub& getMutableRegistryHub() {
6810 return *getTheRegistryHub();
6811 }
cleanUp()6812 void cleanUp() {
6813 delete getTheRegistryHub();
6814 getTheRegistryHub() = CATCH_NULL;
6815 cleanUpContext();
6816 }
translateActiveException()6817 std::string translateActiveException() {
6818 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
6819 }
6820
6821 } // end namespace Catch
6822
6823 // #included from: catch_notimplemented_exception.hpp
6824 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
6825
6826 #include <ostream>
6827
6828 namespace Catch {
6829
NotImplementedException(SourceLineInfo const & lineInfo)6830 NotImplementedException::NotImplementedException(SourceLineInfo const& lineInfo)
6831 : m_lineInfo(lineInfo) {
6832 std::ostringstream oss;
6833 oss << lineInfo << ": function ";
6834 oss << "not implemented";
6835 m_what = oss.str();
6836 }
6837
what() const6838 const char* NotImplementedException::what() const CATCH_NOEXCEPT{
6839 return m_what.c_str();
6840 }
6841
6842 } // end namespace Catch
6843
6844 // #included from: catch_context_impl.hpp
6845 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
6846
6847 // #included from: catch_stream.hpp
6848 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
6849
6850 #include <stdexcept>
6851 #include <cstdio>
6852 #include <iostream>
6853
6854 namespace Catch {
6855
6856 template<typename WriterF, size_t bufferSize = 256>
6857 class StreamBufImpl : public StreamBufBase {
6858 char data[bufferSize];
6859 WriterF m_writer;
6860
6861 public:
StreamBufImpl()6862 StreamBufImpl() {
6863 setp(data, data + sizeof(data));
6864 }
6865
~StreamBufImpl()6866 ~StreamBufImpl() CATCH_NOEXCEPT{
6867 sync();
6868 }
6869
6870 private:
overflow(int c)6871 int overflow(int c) {
6872 sync();
6873
6874 if (c != EOF) {
6875 if (pbase() == epptr())
6876 m_writer(std::string(1, static_cast<char>(c)));
6877 else
6878 sputc(static_cast<char>(c));
6879 }
6880 return 0;
6881 }
6882
sync()6883 int sync() {
6884 if (pbase() != pptr()) {
6885 m_writer(std::string(pbase(), static_cast<std::string::size_type>(pptr() - pbase())));
6886 setp(pbase(), epptr());
6887 }
6888 return 0;
6889 }
6890 };
6891
6892 ///////////////////////////////////////////////////////////////////////////
6893
FileStream(std::string const & filename)6894 FileStream::FileStream(std::string const& filename) {
6895 m_ofs.open(filename.c_str());
6896 if (m_ofs.fail()) {
6897 std::ostringstream oss;
6898 oss << "Unable to open file: '" << filename << "'";
6899 throw std::domain_error(oss.str());
6900 }
6901 }
6902
stream() const6903 std::ostream& FileStream::stream() const {
6904 return m_ofs;
6905 }
6906
6907 struct OutputDebugWriter {
6908
operator ()Catch::OutputDebugWriter6909 void operator()(std::string const&str) {
6910 writeToDebugConsole(str);
6911 }
6912 };
6913
DebugOutStream()6914 DebugOutStream::DebugOutStream()
6915 : m_streamBuf(new StreamBufImpl<OutputDebugWriter>()),
6916 m_os(m_streamBuf.get())
6917 {}
6918
stream() const6919 std::ostream& DebugOutStream::stream() const {
6920 return m_os;
6921 }
6922
6923 // Store the streambuf from cout up-front because
6924 // cout may get redirected when running tests
CoutStream()6925 CoutStream::CoutStream()
6926 : m_os(Catch::cout().rdbuf())
6927 {}
6928
stream() const6929 std::ostream& CoutStream::stream() const {
6930 return m_os;
6931 }
6932
6933 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
cout()6934 std::ostream& cout() {
6935 return std::cout;
6936 }
cerr()6937 std::ostream& cerr() {
6938 return std::cerr;
6939 }
6940 #endif
6941 }
6942
6943 namespace Catch {
6944
6945 class Context : public IMutableContext {
6946
Context()6947 Context() : m_config(CATCH_NULL), m_runner(CATCH_NULL), m_resultCapture(CATCH_NULL) {}
6948 Context(Context const&);
6949 void operator=(Context const&);
6950
6951 public: // IContext
getResultCapture()6952 virtual IResultCapture* getResultCapture() {
6953 return m_resultCapture;
6954 }
getRunner()6955 virtual IRunner* getRunner() {
6956 return m_runner;
6957 }
getGeneratorIndex(std::string const & fileInfo,size_t totalSize)6958 virtual size_t getGeneratorIndex(std::string const& fileInfo, size_t totalSize) {
6959 return getGeneratorsForCurrentTest()
6960 .getGeneratorInfo(fileInfo, totalSize)
6961 .getCurrentIndex();
6962 }
advanceGeneratorsForCurrentTest()6963 virtual bool advanceGeneratorsForCurrentTest() {
6964 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6965 return generators && generators->moveNext();
6966 }
6967
getConfig() const6968 virtual Ptr<IConfig const> getConfig() const {
6969 return m_config;
6970 }
6971
6972 public: // IMutableContext
setResultCapture(IResultCapture * resultCapture)6973 virtual void setResultCapture(IResultCapture* resultCapture) {
6974 m_resultCapture = resultCapture;
6975 }
setRunner(IRunner * runner)6976 virtual void setRunner(IRunner* runner) {
6977 m_runner = runner;
6978 }
setConfig(Ptr<IConfig const> const & config)6979 virtual void setConfig(Ptr<IConfig const> const& config) {
6980 m_config = config;
6981 }
6982
6983 friend IMutableContext& getCurrentMutableContext();
6984
6985 private:
findGeneratorsForCurrentTest()6986 IGeneratorsForTest* findGeneratorsForCurrentTest() {
6987 std::string testName = getResultCapture()->getCurrentTestName();
6988
6989 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
6990 m_generatorsByTestName.find(testName);
6991 return it != m_generatorsByTestName.end()
6992 ? it->second
6993 : CATCH_NULL;
6994 }
6995
getGeneratorsForCurrentTest()6996 IGeneratorsForTest& getGeneratorsForCurrentTest() {
6997 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6998 if (!generators) {
6999 std::string testName = getResultCapture()->getCurrentTestName();
7000 generators = createGeneratorsForTest();
7001 m_generatorsByTestName.insert(std::make_pair(testName, generators));
7002 }
7003 return *generators;
7004 }
7005
7006 private:
7007 Ptr<IConfig const> m_config;
7008 IRunner* m_runner;
7009 IResultCapture* m_resultCapture;
7010 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
7011 };
7012
7013 namespace {
7014 Context* currentContext = CATCH_NULL;
7015 }
getCurrentMutableContext()7016 IMutableContext& getCurrentMutableContext() {
7017 if (!currentContext)
7018 currentContext = new Context();
7019 return *currentContext;
7020 }
getCurrentContext()7021 IContext& getCurrentContext() {
7022 return getCurrentMutableContext();
7023 }
7024
cleanUpContext()7025 void cleanUpContext() {
7026 delete currentContext;
7027 currentContext = CATCH_NULL;
7028 }
7029 }
7030
7031 // #included from: catch_console_colour_impl.hpp
7032 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
7033
7034 namespace Catch {
7035 namespace {
7036
7037 struct IColourImpl {
~IColourImplCatch::__anon2b7cf5a80411::IColourImpl7038 virtual ~IColourImpl() {}
7039 virtual void use(Colour::Code _colourCode) = 0;
7040 };
7041
7042 struct NoColourImpl : IColourImpl {
useCatch::__anon2b7cf5a80411::NoColourImpl7043 void use(Colour::Code) {}
7044
instanceCatch::__anon2b7cf5a80411::NoColourImpl7045 static IColourImpl* instance() {
7046 static NoColourImpl s_instance;
7047 return &s_instance;
7048 }
7049 };
7050
7051 } // anon namespace
7052 } // namespace Catch
7053
7054 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
7055 # ifdef CATCH_PLATFORM_WINDOWS
7056 # define CATCH_CONFIG_COLOUR_WINDOWS
7057 # else
7058 # define CATCH_CONFIG_COLOUR_ANSI
7059 # endif
7060 #endif
7061
7062 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
7063
7064 #ifndef NOMINMAX
7065 #define NOMINMAX
7066 #endif
7067
7068 #ifdef __AFXDLL
7069 #include <AfxWin.h>
7070 #else
7071 #include <windows.h>
7072 #endif
7073
7074 namespace Catch {
7075 namespace {
7076
7077 class Win32ColourImpl : public IColourImpl {
7078 public:
Win32ColourImpl()7079 Win32ColourImpl() : stdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE))
7080 {
7081 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
7082 GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo);
7083 originalForegroundAttributes = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
7084 originalBackgroundAttributes = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
7085 }
7086
use(Colour::Code _colourCode)7087 virtual void use(Colour::Code _colourCode) {
7088 switch (_colourCode) {
7089 case Colour::None: return setTextAttribute(originalForegroundAttributes);
7090 case Colour::White: return setTextAttribute(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE);
7091 case Colour::Red: return setTextAttribute(FOREGROUND_RED);
7092 case Colour::Green: return setTextAttribute(FOREGROUND_GREEN);
7093 case Colour::Blue: return setTextAttribute(FOREGROUND_BLUE);
7094 case Colour::Cyan: return setTextAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN);
7095 case Colour::Yellow: return setTextAttribute(FOREGROUND_RED | FOREGROUND_GREEN);
7096 case Colour::Grey: return setTextAttribute(0);
7097
7098 case Colour::LightGrey: return setTextAttribute(FOREGROUND_INTENSITY);
7099 case Colour::BrightRed: return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_RED);
7100 case Colour::BrightGreen: return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_GREEN);
7101 case Colour::BrightWhite: return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE);
7102
7103 case Colour::Bright: throw std::logic_error("not a colour");
7104 }
7105 }
7106
7107 private:
setTextAttribute(WORD _textAttribute)7108 void setTextAttribute(WORD _textAttribute) {
7109 SetConsoleTextAttribute(stdoutHandle, _textAttribute | originalBackgroundAttributes);
7110 }
7111 HANDLE stdoutHandle;
7112 WORD originalForegroundAttributes;
7113 WORD originalBackgroundAttributes;
7114 };
7115
platformColourInstance()7116 IColourImpl* platformColourInstance() {
7117 static Win32ColourImpl s_instance;
7118
7119 Ptr<IConfig const> config = getCurrentContext().getConfig();
7120 UseColour::YesOrNo colourMode = config
7121 ? config->useColour()
7122 : UseColour::Auto;
7123 if (colourMode == UseColour::Auto)
7124 colourMode = !isDebuggerActive()
7125 ? UseColour::Yes
7126 : UseColour::No;
7127 return colourMode == UseColour::Yes
7128 ? &s_instance
7129 : NoColourImpl::instance();
7130 }
7131
7132 } // end anon namespace
7133 } // end namespace Catch
7134
7135 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
7136
7137 #include <unistd.h>
7138
7139 namespace Catch {
7140 namespace {
7141
7142 // use POSIX/ ANSI console terminal codes
7143 // Thanks to Adam Strzelecki for original contribution
7144 // (http://github.com/nanoant)
7145 // https://github.com/philsquared/Catch/pull/131
7146 class PosixColourImpl : public IColourImpl {
7147 public:
use(Colour::Code _colourCode)7148 virtual void use(Colour::Code _colourCode) {
7149 switch (_colourCode) {
7150 case Colour::None:
7151 case Colour::White: return setColour("[0m");
7152 case Colour::Red: return setColour("[0;31m");
7153 case Colour::Green: return setColour("[0;32m");
7154 case Colour::Blue: return setColour("[0:34m");
7155 case Colour::Cyan: return setColour("[0;36m");
7156 case Colour::Yellow: return setColour("[0;33m");
7157 case Colour::Grey: return setColour("[1;30m");
7158
7159 case Colour::LightGrey: return setColour("[0;37m");
7160 case Colour::BrightRed: return setColour("[1;31m");
7161 case Colour::BrightGreen: return setColour("[1;32m");
7162 case Colour::BrightWhite: return setColour("[1;37m");
7163
7164 case Colour::Bright: throw std::logic_error("not a colour");
7165 }
7166 }
instance()7167 static IColourImpl* instance() {
7168 static PosixColourImpl s_instance;
7169 return &s_instance;
7170 }
7171
7172 private:
setColour(const char * _escapeCode)7173 void setColour(const char* _escapeCode) {
7174 Catch::cout() << '\033' << _escapeCode;
7175 }
7176 };
7177
platformColourInstance()7178 IColourImpl* platformColourInstance() {
7179 Ptr<IConfig const> config = getCurrentContext().getConfig();
7180 UseColour::YesOrNo colourMode = config
7181 ? config->useColour()
7182 : UseColour::Auto;
7183 if (colourMode == UseColour::Auto)
7184 colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO))
7185 ? UseColour::Yes
7186 : UseColour::No;
7187 return colourMode == UseColour::Yes
7188 ? PosixColourImpl::instance()
7189 : NoColourImpl::instance();
7190 }
7191
7192 } // end anon namespace
7193 } // end namespace Catch
7194
7195 #else // not Windows or ANSI ///////////////////////////////////////////////
7196
7197 namespace Catch {
7198
platformColourInstance()7199 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
7200
7201 } // end namespace Catch
7202
7203 #endif // Windows/ ANSI/ None
7204
7205 namespace Catch {
7206
Colour(Code _colourCode)7207 Colour::Colour(Code _colourCode) : m_moved(false) { use(_colourCode); }
Colour(Colour const & _other)7208 Colour::Colour(Colour const& _other) : m_moved(false) { const_cast<Colour&>(_other).m_moved = true; }
~Colour()7209 Colour::~Colour(){ if (!m_moved) use(None); }
7210
use(Code _colourCode)7211 void Colour::use(Code _colourCode) {
7212 static IColourImpl* impl = platformColourInstance();
7213 impl->use(_colourCode);
7214 }
7215
7216 } // end namespace Catch
7217
7218 // #included from: catch_generators_impl.hpp
7219 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
7220
7221 #include <vector>
7222 #include <string>
7223 #include <map>
7224
7225 namespace Catch {
7226
7227 struct GeneratorInfo : IGeneratorInfo {
7228
GeneratorInfoCatch::GeneratorInfo7229 GeneratorInfo(std::size_t size)
7230 : m_size(size),
7231 m_currentIndex(0)
7232 {}
7233
moveNextCatch::GeneratorInfo7234 bool moveNext() {
7235 if (++m_currentIndex == m_size) {
7236 m_currentIndex = 0;
7237 return false;
7238 }
7239 return true;
7240 }
7241
getCurrentIndexCatch::GeneratorInfo7242 std::size_t getCurrentIndex() const {
7243 return m_currentIndex;
7244 }
7245
7246 std::size_t m_size;
7247 std::size_t m_currentIndex;
7248 };
7249
7250 ///////////////////////////////////////////////////////////////////////////
7251
7252 class GeneratorsForTest : public IGeneratorsForTest {
7253
7254 public:
~GeneratorsForTest()7255 ~GeneratorsForTest() {
7256 deleteAll(m_generatorsInOrder);
7257 }
7258
getGeneratorInfo(std::string const & fileInfo,std::size_t size)7259 IGeneratorInfo& getGeneratorInfo(std::string const& fileInfo, std::size_t size) {
7260 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find(fileInfo);
7261 if (it == m_generatorsByName.end()) {
7262 IGeneratorInfo* info = new GeneratorInfo(size);
7263 m_generatorsByName.insert(std::make_pair(fileInfo, info));
7264 m_generatorsInOrder.push_back(info);
7265 return *info;
7266 }
7267 return *it->second;
7268 }
7269
moveNext()7270 bool moveNext() {
7271 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
7272 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
7273 for (; it != itEnd; ++it) {
7274 if ((*it)->moveNext())
7275 return true;
7276 }
7277 return false;
7278 }
7279
7280 private:
7281 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
7282 std::vector<IGeneratorInfo*> m_generatorsInOrder;
7283 };
7284
createGeneratorsForTest()7285 IGeneratorsForTest* createGeneratorsForTest()
7286 {
7287 return new GeneratorsForTest();
7288 }
7289
7290 } // end namespace Catch
7291
7292 // #included from: catch_assertionresult.hpp
7293 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
7294
7295 namespace Catch {
7296
AssertionInfo(std::string const & _macroName,SourceLineInfo const & _lineInfo,std::string const & _capturedExpression,ResultDisposition::Flags _resultDisposition)7297 AssertionInfo::AssertionInfo(std::string const& _macroName,
7298 SourceLineInfo const& _lineInfo,
7299 std::string const& _capturedExpression,
7300 ResultDisposition::Flags _resultDisposition)
7301 : macroName(_macroName),
7302 lineInfo(_lineInfo),
7303 capturedExpression(_capturedExpression),
7304 resultDisposition(_resultDisposition)
7305 {}
7306
AssertionResult()7307 AssertionResult::AssertionResult() {}
7308
AssertionResult(AssertionInfo const & info,AssertionResultData const & data)7309 AssertionResult::AssertionResult(AssertionInfo const& info, AssertionResultData const& data)
7310 : m_info(info),
7311 m_resultData(data)
7312 {}
7313
~AssertionResult()7314 AssertionResult::~AssertionResult() {}
7315
7316 // Result was a success
succeeded() const7317 bool AssertionResult::succeeded() const {
7318 return Catch::isOk(m_resultData.resultType);
7319 }
7320
7321 // Result was a success, or failure is suppressed
isOk() const7322 bool AssertionResult::isOk() const {
7323 return Catch::isOk(m_resultData.resultType) || shouldSuppressFailure(m_info.resultDisposition);
7324 }
7325
getResultType() const7326 ResultWas::OfType AssertionResult::getResultType() const {
7327 return m_resultData.resultType;
7328 }
7329
hasExpression() const7330 bool AssertionResult::hasExpression() const {
7331 return !m_info.capturedExpression.empty();
7332 }
7333
hasMessage() const7334 bool AssertionResult::hasMessage() const {
7335 return !m_resultData.message.empty();
7336 }
7337
getExpression() const7338 std::string AssertionResult::getExpression() const {
7339 if (isFalseTest(m_info.resultDisposition))
7340 return "!" + m_info.capturedExpression;
7341 else
7342 return m_info.capturedExpression;
7343 }
getExpressionInMacro() const7344 std::string AssertionResult::getExpressionInMacro() const {
7345 if (m_info.macroName.empty())
7346 return m_info.capturedExpression;
7347 else
7348 return m_info.macroName + "( " + m_info.capturedExpression + " )";
7349 }
7350
hasExpandedExpression() const7351 bool AssertionResult::hasExpandedExpression() const {
7352 return hasExpression() && getExpandedExpression() != getExpression();
7353 }
7354
getExpandedExpression() const7355 std::string AssertionResult::getExpandedExpression() const {
7356 return m_resultData.reconstructedExpression;
7357 }
7358
getMessage() const7359 std::string AssertionResult::getMessage() const {
7360 return m_resultData.message;
7361 }
getSourceInfo() const7362 SourceLineInfo AssertionResult::getSourceInfo() const {
7363 return m_info.lineInfo;
7364 }
7365
getTestMacroName() const7366 std::string AssertionResult::getTestMacroName() const {
7367 return m_info.macroName;
7368 }
7369
7370 } // end namespace Catch
7371
7372 // #included from: catch_test_case_info.hpp
7373 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
7374
7375 namespace Catch {
7376
parseSpecialTag(std::string const & tag)7377 inline TestCaseInfo::SpecialProperties parseSpecialTag(std::string const& tag) {
7378 if (startsWith(tag, ".") ||
7379 tag == "hide" ||
7380 tag == "!hide")
7381 return TestCaseInfo::IsHidden;
7382 else if (tag == "!throws")
7383 return TestCaseInfo::Throws;
7384 else if (tag == "!shouldfail")
7385 return TestCaseInfo::ShouldFail;
7386 else if (tag == "!mayfail")
7387 return TestCaseInfo::MayFail;
7388 else
7389 return TestCaseInfo::None;
7390 }
isReservedTag(std::string const & tag)7391 inline bool isReservedTag(std::string const& tag) {
7392 return parseSpecialTag(tag) == TestCaseInfo::None && tag.size() > 0 && !isalnum(tag[0]);
7393 }
enforceNotReservedTag(std::string const & tag,SourceLineInfo const & _lineInfo)7394 inline void enforceNotReservedTag(std::string const& tag, SourceLineInfo const& _lineInfo) {
7395 if (isReservedTag(tag)) {
7396 {
7397 Colour colourGuard(Colour::Red);
7398 Catch::cerr()
7399 << "Tag name [" << tag << "] not allowed.\n"
7400 << "Tag names starting with non alpha-numeric characters are reserved\n";
7401 }
7402 {
7403 Colour colourGuard(Colour::FileName);
7404 Catch::cerr() << _lineInfo << std::endl;
7405 }
7406 exit(1);
7407 }
7408 }
7409
makeTestCase(ITestCase * _testCase,std::string const & _className,std::string const & _name,std::string const & _descOrTags,SourceLineInfo const & _lineInfo)7410 TestCase makeTestCase(ITestCase* _testCase,
7411 std::string const& _className,
7412 std::string const& _name,
7413 std::string const& _descOrTags,
7414 SourceLineInfo const& _lineInfo)
7415 {
7416 bool isHidden(startsWith(_name, "./")); // Legacy support
7417
7418 // Parse out tags
7419 std::set<std::string> tags;
7420 std::string desc, tag;
7421 bool inTag = false;
7422 for (std::size_t i = 0; i < _descOrTags.size(); ++i) {
7423 char c = _descOrTags[i];
7424 if (!inTag) {
7425 if (c == '[')
7426 inTag = true;
7427 else
7428 desc += c;
7429 }
7430 else {
7431 if (c == ']') {
7432 TestCaseInfo::SpecialProperties prop = parseSpecialTag(tag);
7433 if (prop == TestCaseInfo::IsHidden)
7434 isHidden = true;
7435 else if (prop == TestCaseInfo::None)
7436 enforceNotReservedTag(tag, _lineInfo);
7437
7438 tags.insert(tag);
7439 tag.clear();
7440 inTag = false;
7441 }
7442 else
7443 tag += c;
7444 }
7445 }
7446 if (isHidden) {
7447 tags.insert("hide");
7448 tags.insert(".");
7449 }
7450
7451 TestCaseInfo info(_name, _className, desc, tags, _lineInfo);
7452 return TestCase(_testCase, info);
7453 }
7454
setTags(TestCaseInfo & testCaseInfo,std::set<std::string> const & tags)7455 void setTags(TestCaseInfo& testCaseInfo, std::set<std::string> const& tags)
7456 {
7457 testCaseInfo.tags = tags;
7458 testCaseInfo.lcaseTags.clear();
7459
7460 std::ostringstream oss;
7461 for (std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it) {
7462 oss << "[" << *it << "]";
7463 std::string lcaseTag = toLower(*it);
7464 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>(testCaseInfo.properties | parseSpecialTag(lcaseTag));
7465 testCaseInfo.lcaseTags.insert(lcaseTag);
7466 }
7467 testCaseInfo.tagsAsString = oss.str();
7468 }
7469
TestCaseInfo(std::string const & _name,std::string const & _className,std::string const & _description,std::set<std::string> const & _tags,SourceLineInfo const & _lineInfo)7470 TestCaseInfo::TestCaseInfo(std::string const& _name,
7471 std::string const& _className,
7472 std::string const& _description,
7473 std::set<std::string> const& _tags,
7474 SourceLineInfo const& _lineInfo)
7475 : name(_name),
7476 className(_className),
7477 description(_description),
7478 lineInfo(_lineInfo),
7479 properties(None)
7480 {
7481 setTags(*this, _tags);
7482 }
7483
TestCaseInfo(TestCaseInfo const & other)7484 TestCaseInfo::TestCaseInfo(TestCaseInfo const& other)
7485 : name(other.name),
7486 className(other.className),
7487 description(other.description),
7488 tags(other.tags),
7489 lcaseTags(other.lcaseTags),
7490 tagsAsString(other.tagsAsString),
7491 lineInfo(other.lineInfo),
7492 properties(other.properties)
7493 {}
7494
isHidden() const7495 bool TestCaseInfo::isHidden() const {
7496 return (properties & IsHidden) != 0;
7497 }
throws() const7498 bool TestCaseInfo::throws() const {
7499 return (properties & Throws) != 0;
7500 }
okToFail() const7501 bool TestCaseInfo::okToFail() const {
7502 return (properties & (ShouldFail | MayFail)) != 0;
7503 }
expectedToFail() const7504 bool TestCaseInfo::expectedToFail() const {
7505 return (properties & (ShouldFail)) != 0;
7506 }
7507
TestCase(ITestCase * testCase,TestCaseInfo const & info)7508 TestCase::TestCase(ITestCase* testCase, TestCaseInfo const& info) : TestCaseInfo(info), test(testCase) {}
7509
TestCase(TestCase const & other)7510 TestCase::TestCase(TestCase const& other)
7511 : TestCaseInfo(other),
7512 test(other.test)
7513 {}
7514
withName(std::string const & _newName) const7515 TestCase TestCase::withName(std::string const& _newName) const {
7516 TestCase other(*this);
7517 other.name = _newName;
7518 return other;
7519 }
7520
swap(TestCase & other)7521 void TestCase::swap(TestCase& other) {
7522 test.swap(other.test);
7523 name.swap(other.name);
7524 className.swap(other.className);
7525 description.swap(other.description);
7526 tags.swap(other.tags);
7527 lcaseTags.swap(other.lcaseTags);
7528 tagsAsString.swap(other.tagsAsString);
7529 std::swap(TestCaseInfo::properties, static_cast<TestCaseInfo&>(other).properties);
7530 std::swap(lineInfo, other.lineInfo);
7531 }
7532
invoke() const7533 void TestCase::invoke() const {
7534 test->invoke();
7535 }
7536
operator ==(TestCase const & other) const7537 bool TestCase::operator == (TestCase const& other) const {
7538 return test.get() == other.test.get() &&
7539 name == other.name &&
7540 className == other.className;
7541 }
7542
operator <(TestCase const & other) const7543 bool TestCase::operator < (TestCase const& other) const {
7544 return name < other.name;
7545 }
operator =(TestCase const & other)7546 TestCase& TestCase::operator = (TestCase const& other) {
7547 TestCase temp(other);
7548 swap(temp);
7549 return *this;
7550 }
7551
getTestCaseInfo() const7552 TestCaseInfo const& TestCase::getTestCaseInfo() const
7553 {
7554 return *this;
7555 }
7556
7557 } // end namespace Catch
7558
7559 // #included from: catch_version.hpp
7560 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
7561
7562 namespace Catch {
7563
Version(unsigned int _majorVersion,unsigned int _minorVersion,unsigned int _patchNumber,std::string const & _branchName,unsigned int _buildNumber)7564 Version::Version
7565 (unsigned int _majorVersion,
7566 unsigned int _minorVersion,
7567 unsigned int _patchNumber,
7568 std::string const& _branchName,
7569 unsigned int _buildNumber)
7570 : majorVersion(_majorVersion),
7571 minorVersion(_minorVersion),
7572 patchNumber(_patchNumber),
7573 branchName(_branchName),
7574 buildNumber(_buildNumber)
7575 {}
7576
operator <<(std::ostream & os,Version const & version)7577 std::ostream& operator << (std::ostream& os, Version const& version) {
7578 os << version.majorVersion << "."
7579 << version.minorVersion << "."
7580 << version.patchNumber;
7581
7582 if (!version.branchName.empty()) {
7583 os << "-" << version.branchName
7584 << "." << version.buildNumber;
7585 }
7586 return os;
7587 }
7588
7589 Version libraryVersion(1, 5, 6, "", 0);
7590
7591 }
7592
7593 // #included from: catch_message.hpp
7594 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
7595
7596 namespace Catch {
7597
MessageInfo(std::string const & _macroName,SourceLineInfo const & _lineInfo,ResultWas::OfType _type)7598 MessageInfo::MessageInfo(std::string const& _macroName,
7599 SourceLineInfo const& _lineInfo,
7600 ResultWas::OfType _type)
7601 : macroName(_macroName),
7602 lineInfo(_lineInfo),
7603 type(_type),
7604 sequence(++globalCount)
7605 {}
7606
7607 // This may need protecting if threading support is added
7608 unsigned int MessageInfo::globalCount = 0;
7609
7610 ////////////////////////////////////////////////////////////////////////////
7611
ScopedMessage(MessageBuilder const & builder)7612 ScopedMessage::ScopedMessage(MessageBuilder const& builder)
7613 : m_info(builder.m_info)
7614 {
7615 m_info.message = builder.m_stream.str();
7616 getResultCapture().pushScopedMessage(m_info);
7617 }
ScopedMessage(ScopedMessage const & other)7618 ScopedMessage::ScopedMessage(ScopedMessage const& other)
7619 : m_info(other.m_info)
7620 {}
7621
~ScopedMessage()7622 ScopedMessage::~ScopedMessage() {
7623 getResultCapture().popScopedMessage(m_info);
7624 }
7625
7626 } // end namespace Catch
7627
7628 // #included from: catch_legacy_reporter_adapter.hpp
7629 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
7630
7631 // #included from: catch_legacy_reporter_adapter.h
7632 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
7633
7634 namespace Catch
7635 {
7636 // Deprecated
7637 struct IReporter : IShared {
7638 virtual ~IReporter();
7639
7640 virtual bool shouldRedirectStdout() const = 0;
7641
7642 virtual void StartTesting() = 0;
7643 virtual void EndTesting(Totals const& totals) = 0;
7644 virtual void StartGroup(std::string const& groupName) = 0;
7645 virtual void EndGroup(std::string const& groupName, Totals const& totals) = 0;
7646 virtual void StartTestCase(TestCaseInfo const& testInfo) = 0;
7647 virtual void EndTestCase(TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr) = 0;
7648 virtual void StartSection(std::string const& sectionName, std::string const& description) = 0;
7649 virtual void EndSection(std::string const& sectionName, Counts const& assertions) = 0;
7650 virtual void NoAssertionsInSection(std::string const& sectionName) = 0;
7651 virtual void NoAssertionsInTestCase(std::string const& testName) = 0;
7652 virtual void Aborted() = 0;
7653 virtual void Result(AssertionResult const& result) = 0;
7654 };
7655
7656 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
7657 {
7658 public:
7659 LegacyReporterAdapter(Ptr<IReporter> const& legacyReporter);
7660 virtual ~LegacyReporterAdapter();
7661
7662 virtual ReporterPreferences getPreferences() const;
7663 virtual void noMatchingTestCases(std::string const&);
7664 virtual void testRunStarting(TestRunInfo const&);
7665 virtual void testGroupStarting(GroupInfo const& groupInfo);
7666 virtual void testCaseStarting(TestCaseInfo const& testInfo);
7667 virtual void sectionStarting(SectionInfo const& sectionInfo);
7668 virtual void assertionStarting(AssertionInfo const&);
7669 virtual bool assertionEnded(AssertionStats const& assertionStats);
7670 virtual void sectionEnded(SectionStats const& sectionStats);
7671 virtual void testCaseEnded(TestCaseStats const& testCaseStats);
7672 virtual void testGroupEnded(TestGroupStats const& testGroupStats);
7673 virtual void testRunEnded(TestRunStats const& testRunStats);
7674 virtual void skipTest(TestCaseInfo const&);
7675
7676 private:
7677 Ptr<IReporter> m_legacyReporter;
7678 };
7679 }
7680
7681 namespace Catch
7682 {
LegacyReporterAdapter(Ptr<IReporter> const & legacyReporter)7683 LegacyReporterAdapter::LegacyReporterAdapter(Ptr<IReporter> const& legacyReporter)
7684 : m_legacyReporter(legacyReporter)
7685 {}
~LegacyReporterAdapter()7686 LegacyReporterAdapter::~LegacyReporterAdapter() {}
7687
getPreferences() const7688 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
7689 ReporterPreferences prefs;
7690 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
7691 return prefs;
7692 }
7693
noMatchingTestCases(std::string const &)7694 void LegacyReporterAdapter::noMatchingTestCases(std::string const&) {}
testRunStarting(TestRunInfo const &)7695 void LegacyReporterAdapter::testRunStarting(TestRunInfo const&) {
7696 m_legacyReporter->StartTesting();
7697 }
testGroupStarting(GroupInfo const & groupInfo)7698 void LegacyReporterAdapter::testGroupStarting(GroupInfo const& groupInfo) {
7699 m_legacyReporter->StartGroup(groupInfo.name);
7700 }
testCaseStarting(TestCaseInfo const & testInfo)7701 void LegacyReporterAdapter::testCaseStarting(TestCaseInfo const& testInfo) {
7702 m_legacyReporter->StartTestCase(testInfo);
7703 }
sectionStarting(SectionInfo const & sectionInfo)7704 void LegacyReporterAdapter::sectionStarting(SectionInfo const& sectionInfo) {
7705 m_legacyReporter->StartSection(sectionInfo.name, sectionInfo.description);
7706 }
assertionStarting(AssertionInfo const &)7707 void LegacyReporterAdapter::assertionStarting(AssertionInfo const&) {
7708 // Not on legacy interface
7709 }
7710
assertionEnded(AssertionStats const & assertionStats)7711 bool LegacyReporterAdapter::assertionEnded(AssertionStats const& assertionStats) {
7712 if (assertionStats.assertionResult.getResultType() != ResultWas::Ok) {
7713 for (std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
7714 it != itEnd;
7715 ++it) {
7716 if (it->type == ResultWas::Info) {
7717 ResultBuilder rb(it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal);
7718 rb << it->message;
7719 rb.setResultType(ResultWas::Info);
7720 AssertionResult result = rb.build();
7721 m_legacyReporter->Result(result);
7722 }
7723 }
7724 }
7725 m_legacyReporter->Result(assertionStats.assertionResult);
7726 return true;
7727 }
sectionEnded(SectionStats const & sectionStats)7728 void LegacyReporterAdapter::sectionEnded(SectionStats const& sectionStats) {
7729 if (sectionStats.missingAssertions)
7730 m_legacyReporter->NoAssertionsInSection(sectionStats.sectionInfo.name);
7731 m_legacyReporter->EndSection(sectionStats.sectionInfo.name, sectionStats.assertions);
7732 }
testCaseEnded(TestCaseStats const & testCaseStats)7733 void LegacyReporterAdapter::testCaseEnded(TestCaseStats const& testCaseStats) {
7734 m_legacyReporter->EndTestCase
7735 (testCaseStats.testInfo,
7736 testCaseStats.totals,
7737 testCaseStats.stdOut,
7738 testCaseStats.stdErr);
7739 }
testGroupEnded(TestGroupStats const & testGroupStats)7740 void LegacyReporterAdapter::testGroupEnded(TestGroupStats const& testGroupStats) {
7741 if (testGroupStats.aborting)
7742 m_legacyReporter->Aborted();
7743 m_legacyReporter->EndGroup(testGroupStats.groupInfo.name, testGroupStats.totals);
7744 }
testRunEnded(TestRunStats const & testRunStats)7745 void LegacyReporterAdapter::testRunEnded(TestRunStats const& testRunStats) {
7746 m_legacyReporter->EndTesting(testRunStats.totals);
7747 }
skipTest(TestCaseInfo const &)7748 void LegacyReporterAdapter::skipTest(TestCaseInfo const&) {
7749 }
7750 }
7751
7752 // #included from: catch_timer.hpp
7753
7754 #ifdef __clang__
7755 #pragma clang diagnostic push
7756 #pragma clang diagnostic ignored "-Wc++11-long-long"
7757 #endif
7758
7759 #ifdef CATCH_PLATFORM_WINDOWS
7760 #include <windows.h>
7761 #else
7762 #include <sys/time.h>
7763 #endif
7764
7765 namespace Catch {
7766
7767 namespace {
7768 #ifdef CATCH_PLATFORM_WINDOWS
getCurrentTicks()7769 uint64_t getCurrentTicks() {
7770 static uint64_t hz = 0, hzo = 0;
7771 if (!hz) {
7772 QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&hz));
7773 QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&hzo));
7774 }
7775 uint64_t t;
7776 QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&t));
7777 return ((t - hzo) * 1000000) / hz;
7778 }
7779 #else
7780 uint64_t getCurrentTicks() {
7781 timeval t;
7782 gettimeofday(&t, CATCH_NULL);
7783 return static_cast<uint64_t>(t.tv_sec) * 1000000ull + static_cast<uint64_t>(t.tv_usec);
7784 }
7785 #endif
7786 }
7787
start()7788 void Timer::start() {
7789 m_ticks = getCurrentTicks();
7790 }
getElapsedMicroseconds() const7791 unsigned int Timer::getElapsedMicroseconds() const {
7792 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
7793 }
getElapsedMilliseconds() const7794 unsigned int Timer::getElapsedMilliseconds() const {
7795 return static_cast<unsigned int>(getElapsedMicroseconds() / 1000);
7796 }
getElapsedSeconds() const7797 double Timer::getElapsedSeconds() const {
7798 return getElapsedMicroseconds() / 1000000.0;
7799 }
7800
7801 } // namespace Catch
7802
7803 #ifdef __clang__
7804 #pragma clang diagnostic pop
7805 #endif
7806 // #included from: catch_common.hpp
7807 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
7808
7809 namespace Catch {
7810
startsWith(std::string const & s,std::string const & prefix)7811 bool startsWith(std::string const& s, std::string const& prefix) {
7812 return s.size() >= prefix.size() && s.substr(0, prefix.size()) == prefix;
7813 }
endsWith(std::string const & s,std::string const & suffix)7814 bool endsWith(std::string const& s, std::string const& suffix) {
7815 return s.size() >= suffix.size() && s.substr(s.size() - suffix.size(), suffix.size()) == suffix;
7816 }
contains(std::string const & s,std::string const & infix)7817