1 /*
2 * Catch v1.3.2
3 * Generated: 2015-12-28 15:07:07.166291
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 #define INTERNAL_CATCH_UNIQUE_NAME(name) INTERNAL_CATCH_UNIQUE_NAME_LINE(name, __LINE__)
66
67 #define INTERNAL_CATCH_STRINGIFY2(expr) #expr
68 #define INTERNAL_CATCH_STRINGIFY(expr) INTERNAL_CATCH_STRINGIFY2(expr)
69
70 #include <algorithm>
71 #include <sstream>
72 #include <stdexcept>
73
74 // #included from: catch_compiler_capabilities.h
75 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
76
77 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler
78 // The following features are defined:
79 //
80 // CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
81 // CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
82 // CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
83 // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
84 // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
85 // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
86 // CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
87 // CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
88
89 // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
90
91 // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
92
93 // ****************
94 // Note to maintainers: if new toggles are added please document them
95 // in configuration.md, too
96 // ****************
97
98 // In general each macro has a _NO_<feature name> form
99 // (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
100 // Many features, at point of detection, define an _INTERNAL_ macro, so they
101 // can be combined, en-mass, with the _NO_ forms later.
102
103 // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
104
105 #ifdef __clang__
106
107 #if __has_feature(cxx_nullptr)
108 #define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
109 #endif
110
111 #if __has_feature(cxx_noexcept)
112 #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
113 #endif
114
115 #endif // __clang__
116
117 ////////////////////////////////////////////////////////////////////////////////
118 // Borland
119 #ifdef __BORLANDC__
120
121 #endif // __BORLANDC__
122
123 ////////////////////////////////////////////////////////////////////////////////
124 // EDG
125 #ifdef __EDG_VERSION__
126
127 #endif // __EDG_VERSION__
128
129 ////////////////////////////////////////////////////////////////////////////////
130 // Digital Mars
131 #ifdef __DMC__
132
133 #endif // __DMC__
134
135 ////////////////////////////////////////////////////////////////////////////////
136 // GCC
137 #ifdef __GNUC__
138
139 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
140 #define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
141 #endif
142
143 // - otherwise more recent versions define __cplusplus >= 201103L
144 // and will get picked up below
145
146 #endif // __GNUC__
147
148 ////////////////////////////////////////////////////////////////////////////////
149 // Visual C++
150 #ifdef _MSC_VER
151
152 #if (_MSC_VER >= 1600)
153 #define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
154 #define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
155 #endif
156
157 #if (_MSC_VER >= 1900) // (VC++ 13 (VS2015))
158 #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
159 #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
160 #endif
161
162 #endif // _MSC_VER
163
164 ////////////////////////////////////////////////////////////////////////////////
165
166 // Use variadic macros if the compiler supports them
167 #if (defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
168 (defined __WAVE__ && __WAVE_HAS_VARIADICS) || \
169 (defined __GNUC__ && __GNUC__ >= 3) || \
170 (!defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L)
171
172 #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
173
174 #endif
175
176 ////////////////////////////////////////////////////////////////////////////////
177 // C++ language feature support
178
179 // catch all support for C++11
180 #if defined(__cplusplus) && __cplusplus >= 201103L
181
182 #define CATCH_CPP11_OR_GREATER
183
184 #if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
185 #define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
186 #endif
187
188 #ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
189 #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
190 #endif
191
192 #ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
193 #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
194 #endif
195
196 #ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
197 #define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
198 #endif
199
200 #ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
201 #define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
202 #endif
203
204 #ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
205 #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
206 #endif
207
208 #if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
209 #define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
210 #endif
211
212 #if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
213 #define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
214 #endif
215 #if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
216 #define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
217 #endif
218
219 #endif // __cplusplus >= 201103L
220
221 // Now set the actual defines based on the above + anything the user has configured
222 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
223 #define CATCH_CONFIG_CPP11_NULLPTR
224 #endif
225 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
226 #define CATCH_CONFIG_CPP11_NOEXCEPT
227 #endif
228 #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)
229 #define CATCH_CONFIG_CPP11_GENERATED_METHODS
230 #endif
231 #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)
232 #define CATCH_CONFIG_CPP11_IS_ENUM
233 #endif
234 #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
235 #define CATCH_CONFIG_CPP11_TUPLE
236 #endif
237 #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
238 #define CATCH_CONFIG_VARIADIC_MACROS
239 #endif
240 #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)
241 #define CATCH_CONFIG_CPP11_LONG_LONG
242 #endif
243 #if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
244 #define CATCH_CONFIG_CPP11_OVERRIDE
245 #endif
246 #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)
247 #define CATCH_CONFIG_CPP11_UNIQUE_PTR
248 #endif
249
250 // noexcept support:
251 #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
252 #define CATCH_NOEXCEPT noexcept
253 #define CATCH_NOEXCEPT_IS(x) noexcept(x)
254 #else
255 #define CATCH_NOEXCEPT throw()
256 #define CATCH_NOEXCEPT_IS(x)
257 #endif
258
259 // nullptr support
260 #ifdef CATCH_CONFIG_CPP11_NULLPTR
261 #define CATCH_NULL nullptr
262 #else
263 #define CATCH_NULL NULL
264 #endif
265
266 // override support
267 #ifdef CATCH_CONFIG_CPP11_OVERRIDE
268 #define CATCH_OVERRIDE override
269 #else
270 #define CATCH_OVERRIDE
271 #endif
272
273 // unique_ptr support
274 #ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
275 #define CATCH_AUTO_PTR(T) std::unique_ptr<T>
276 #else
277 #define CATCH_AUTO_PTR(T) std::auto_ptr<T>
278 #endif
279
280 namespace Catch {
281
282 struct IConfig;
283
284 struct CaseSensitive
285 {
286 enum Choice
287 {
288 Yes,
289 No
290 };
291 };
292
293 class NonCopyable
294 {
295 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
296 NonCopyable(NonCopyable const&) = delete;
297 NonCopyable(NonCopyable&&) = delete;
298 NonCopyable& operator=(NonCopyable const&) = delete;
299 NonCopyable& operator=(NonCopyable&&) = delete;
300 #else
301 NonCopyable(NonCopyable const& info);
302 NonCopyable& operator=(NonCopyable const&);
303 #endif
304
305 protected:
NonCopyable()306 NonCopyable() {}
307 virtual ~NonCopyable();
308 };
309
310 class SafeBool
311 {
312 public:
313 typedef void (SafeBool::*type)() const;
314
makeSafe(bool value)315 static type makeSafe(bool value)
316 {
317 return value ? &SafeBool::trueValue : 0;
318 }
319
320 private:
trueValue() const321 void trueValue() const {}
322 };
323
324 template <typename ContainerT>
deleteAll(ContainerT & container)325 inline void deleteAll(ContainerT& container)
326 {
327 typename ContainerT::const_iterator it = container.begin();
328 typename ContainerT::const_iterator itEnd = container.end();
329 for (; it != itEnd; ++it)
330 delete *it;
331 }
332 template <typename AssociativeContainerT>
deleteAllValues(AssociativeContainerT & container)333 inline void deleteAllValues(AssociativeContainerT& container)
334 {
335 typename AssociativeContainerT::const_iterator it = container.begin();
336 typename AssociativeContainerT::const_iterator itEnd = container.end();
337 for (; it != itEnd; ++it)
338 delete it->second;
339 }
340
341 bool startsWith(std::string const& s, std::string const& prefix);
342 bool endsWith(std::string const& s, std::string const& suffix);
343 bool contains(std::string const& s, std::string const& infix);
344 void toLowerInPlace(std::string& s);
345 std::string toLower(std::string const& s);
346 std::string trim(std::string const& str);
347 bool replaceInPlace(std::string& str, std::string const& replaceThis, std::string const& withThis);
348
349 struct pluralise
350 {
351 pluralise(std::size_t count, std::string const& label);
352
353 friend std::ostream& operator<<(std::ostream& os, pluralise const& pluraliser);
354
355 std::size_t m_count;
356 std::string m_label;
357 };
358
359 struct SourceLineInfo
360 {
361
362 SourceLineInfo();
363 SourceLineInfo(char const* _file, std::size_t _line);
364 SourceLineInfo(SourceLineInfo const& other);
365 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
366 SourceLineInfo(SourceLineInfo&&) = default;
367 SourceLineInfo& operator=(SourceLineInfo const&) = default;
368 SourceLineInfo& operator=(SourceLineInfo&&) = default;
369 #endif
370 bool empty() const;
371 bool operator==(SourceLineInfo const& other) const;
372 bool operator<(SourceLineInfo const& other) const;
373
374 std::string file;
375 std::size_t line;
376 };
377
378 std::ostream& operator<<(std::ostream& os, SourceLineInfo const& info);
379
380 // This is just here to avoid compiler warnings with macro constants and boolean literals
isTrue(bool value)381 inline bool isTrue(bool value) { return value; }
alwaysTrue()382 inline bool alwaysTrue() { return true; }
alwaysFalse()383 inline bool alwaysFalse() { return false; }
384
385 void throwLogicError(std::string const& message, SourceLineInfo const& locationInfo);
386
387 void seedRng(IConfig const& config);
388 unsigned int rngSeed();
389
390 // Use this in variadic streaming macros to allow
391 // >> +StreamEndStop
392 // as well as
393 // >> stuff +StreamEndStop
394 struct StreamEndStop
395 {
operator +Catch::StreamEndStop396 std::string operator+()
397 {
398 return std::string();
399 }
400 };
401 template <typename T>
operator +(T const & value,StreamEndStop)402 T const& operator+(T const& value, StreamEndStop)
403 {
404 return value;
405 }
406 }
407
408 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo(__FILE__, static_cast<std::size_t>(__LINE__))
409 #define CATCH_INTERNAL_ERROR(msg) ::Catch::throwLogicError(msg, CATCH_INTERNAL_LINEINFO);
410
411 #include <ostream>
412
413 namespace Catch {
414
415 class NotImplementedException : public std::exception
416 {
417 public:
418 NotImplementedException(SourceLineInfo const& lineInfo);
NotImplementedException(NotImplementedException const &)419 NotImplementedException(NotImplementedException const&) {}
420
~NotImplementedException()421 virtual ~NotImplementedException() CATCH_NOEXCEPT {}
422
423 virtual const char* what() const CATCH_NOEXCEPT;
424
425 private:
426 std::string m_what;
427 SourceLineInfo m_lineInfo;
428 };
429
430 } // end namespace Catch
431
432 ///////////////////////////////////////////////////////////////////////////////
433 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException(CATCH_INTERNAL_LINEINFO)
434
435 // #included from: internal/catch_context.h
436 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
437
438 // #included from: catch_interfaces_generators.h
439 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
440
441 #include <string>
442
443 namespace Catch {
444
445 struct IGeneratorInfo
446 {
447 virtual ~IGeneratorInfo();
448 virtual bool moveNext() = 0;
449 virtual std::size_t getCurrentIndex() const = 0;
450 };
451
452 struct IGeneratorsForTest
453 {
454 virtual ~IGeneratorsForTest();
455
456 virtual IGeneratorInfo& getGeneratorInfo(std::string const& fileInfo, std::size_t size) = 0;
457 virtual bool moveNext() = 0;
458 };
459
460 IGeneratorsForTest* createGeneratorsForTest();
461
462 } // end namespace Catch
463
464 // #included from: catch_ptr.hpp
465 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
466
467 #ifdef __clang__
468 #pragma clang diagnostic push
469 #pragma clang diagnostic ignored "-Wpadded"
470 #endif
471
472 namespace Catch {
473
474 // An intrusive reference counting smart pointer.
475 // T must implement addRef() and release() methods
476 // typically implementing the IShared interface
477 template <typename T>
478 class Ptr
479 {
480 public:
Ptr()481 Ptr() : m_p(CATCH_NULL) {}
Ptr(T * p)482 Ptr(T* p) : m_p(p)
483 {
484 if (m_p)
485 m_p->addRef();
486 }
Ptr(Ptr const & other)487 Ptr(Ptr const& other) : m_p(other.m_p)
488 {
489 if (m_p)
490 m_p->addRef();
491 }
~Ptr()492 ~Ptr()
493 {
494 if (m_p)
495 m_p->release();
496 }
reset()497 void reset()
498 {
499 if (m_p)
500 m_p->release();
501 m_p = CATCH_NULL;
502 }
operator =(T * p)503 Ptr& operator=(T* p)
504 {
505 Ptr temp(p);
506 swap(temp);
507 return *this;
508 }
operator =(Ptr const & other)509 Ptr& operator=(Ptr const& other)
510 {
511 Ptr temp(other);
512 swap(temp);
513 return *this;
514 }
swap(Ptr & other)515 void swap(Ptr& other) { std::swap(m_p, other.m_p); }
get() const516 T* get() const { return m_p; }
operator *() const517 T& operator*() const { return *m_p; }
operator ->() const518 T* operator->() const { return m_p; }
operator !() const519 bool operator!() const { return m_p == CATCH_NULL; }
operator SafeBool::type() const520 operator SafeBool::type() const { return SafeBool::makeSafe(m_p != CATCH_NULL); }
521
522 private:
523 T* m_p;
524 };
525
526 struct IShared : NonCopyable
527 {
528 virtual ~IShared();
529 virtual void addRef() const = 0;
530 virtual void release() const = 0;
531 };
532
533 template <typename T = IShared>
534 struct SharedImpl : T
535 {
536
SharedImplCatch::SharedImpl537 SharedImpl() : m_rc(0) {}
538
addRefCatch::SharedImpl539 virtual void addRef() const
540 {
541 ++m_rc;
542 }
releaseCatch::SharedImpl543 virtual void release() const
544 {
545 if (--m_rc == 0)
546 delete this;
547 }
548
549 mutable unsigned int m_rc;
550 };
551
552 } // end namespace Catch
553
554 #ifdef __clang__
555 #pragma clang diagnostic pop
556 #endif
557
558 #include <memory>
559 #include <stdlib.h>
560 #include <vector>
561
562 namespace Catch {
563
564 class TestCase;
565 class Stream;
566 struct IResultCapture;
567 struct IRunner;
568 struct IGeneratorsForTest;
569 struct IConfig;
570
571 struct IContext
572 {
573 virtual ~IContext();
574
575 virtual IResultCapture* getResultCapture() = 0;
576 virtual IRunner* getRunner() = 0;
577 virtual size_t getGeneratorIndex(std::string const& fileInfo, size_t totalSize) = 0;
578 virtual bool advanceGeneratorsForCurrentTest() = 0;
579 virtual Ptr<IConfig const> getConfig() const = 0;
580 };
581
582 struct IMutableContext : IContext
583 {
584 virtual ~IMutableContext();
585 virtual void setResultCapture(IResultCapture* resultCapture) = 0;
586 virtual void setRunner(IRunner* runner) = 0;
587 virtual void setConfig(Ptr<IConfig const> const& config) = 0;
588 };
589
590 IContext& getCurrentContext();
591 IMutableContext& getCurrentMutableContext();
592 void cleanUpContext();
593 Stream createStream(std::string const& streamName);
594 }
595
596 // #included from: internal/catch_test_registry.hpp
597 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
598
599 // #included from: catch_interfaces_testcase.h
600 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
601
602 #include <vector>
603
604 namespace Catch {
605
606 class TestSpec;
607
608 struct ITestCase : IShared
609 {
610 virtual void invoke() const = 0;
611
612 protected:
613 virtual ~ITestCase();
614 };
615
616 class TestCase;
617 struct IConfig;
618
619 struct ITestCaseRegistry
620 {
621 virtual ~ITestCaseRegistry();
622 virtual std::vector<TestCase> const& getAllTests() const = 0;
623 virtual std::vector<TestCase> const& getAllTestsSorted(IConfig const& config) const = 0;
624 };
625
626 bool matchTest(TestCase const& testCase, TestSpec const& testSpec, IConfig const& config);
627 std::vector<TestCase> filterTests(std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config);
628 std::vector<TestCase> const& getAllTestCasesSorted(IConfig const& config);
629 }
630
631 namespace Catch {
632
633 template <typename C>
634 class MethodTestCase : public SharedImpl<ITestCase>
635 {
636
637 public:
MethodTestCase(void (C::* method)())638 MethodTestCase(void (C::*method)()) : m_method(method) {}
639
invoke() const640 virtual void invoke() const
641 {
642 C obj;
643 (obj.*m_method)();
644 }
645
646 private:
~MethodTestCase()647 virtual ~MethodTestCase() {}
648
649 void (C::*m_method)();
650 };
651
652 typedef void (*TestFunction)();
653
654 struct NameAndDesc
655 {
NameAndDescCatch::NameAndDesc656 NameAndDesc(const char* _name = "", const char* _description = "")
657 : name(_name), description(_description)
658 {
659 }
660
661 const char* name;
662 const char* description;
663 };
664
665 void registerTestCase(ITestCase* testCase,
666 char const* className,
667 NameAndDesc const& nameAndDesc,
668 SourceLineInfo const& lineInfo);
669
670 struct AutoReg
671 {
672
673 AutoReg(TestFunction function,
674 SourceLineInfo const& lineInfo,
675 NameAndDesc const& nameAndDesc);
676
677 template <typename C>
AutoRegCatch::AutoReg678 AutoReg(void (C::*method)(),
679 char const* className,
680 NameAndDesc const& nameAndDesc,
681 SourceLineInfo const& lineInfo)
682 {
683
684 registerTestCase(new MethodTestCase<C>(method),
685 className,
686 nameAndDesc,
687 lineInfo);
688 }
689
690 ~AutoReg();
691
692 private:
693 AutoReg(AutoReg const&);
694 void operator=(AutoReg const&);
695 };
696
697 void registerTestCaseFunction(TestFunction function,
698 SourceLineInfo const& lineInfo,
699 NameAndDesc const& nameAndDesc);
700
701 } // end namespace Catch
702
703 #ifdef CATCH_CONFIG_VARIADIC_MACROS
704 ///////////////////////////////////////////////////////////////////////////////
705 #define INTERNAL_CATCH_TESTCASE(...) \
706 static void INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)(); \
707 namespace { \
708 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)(&INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc(__VA_ARGS__)); \
709 } \
710 static void INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)()
711
712 ///////////////////////////////////////////////////////////////////////////////
713 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE(QualifiedMethod, ...) \
714 namespace { \
715 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)(&QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc(__VA_ARGS__), CATCH_INTERNAL_LINEINFO); \
716 }
717
718 ///////////////////////////////////////////////////////////////////////////////
719 #define INTERNAL_CATCH_TEST_CASE_METHOD(ClassName, ...) \
720 namespace { \
721 struct INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____) : ClassName \
722 { \
723 void test(); \
724 }; \
725 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)(&INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)::test, #ClassName, Catch::NameAndDesc(__VA_ARGS__), CATCH_INTERNAL_LINEINFO); \
726 } \
727 void INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)::test()
728
729 ///////////////////////////////////////////////////////////////////////////////
730 #define INTERNAL_CATCH_REGISTER_TESTCASE(Function, ...) \
731 Catch::AutoReg(Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc(__VA_ARGS__));
732
733 #else
734 ///////////////////////////////////////////////////////////////////////////////
735 #define INTERNAL_CATCH_TESTCASE(Name, Desc) \
736 static void INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)(); \
737 namespace { \
738 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)(&INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc(Name, Desc)); \
739 } \
740 static void INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)()
741
742 ///////////////////////////////////////////////////////////////////////////////
743 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE(QualifiedMethod, Name, Desc) \
744 namespace { \
745 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)(&QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc(Name, Desc), CATCH_INTERNAL_LINEINFO); \
746 }
747
748 ///////////////////////////////////////////////////////////////////////////////
749 #define INTERNAL_CATCH_TEST_CASE_METHOD(ClassName, TestName, Desc) \
750 namespace { \
751 struct INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____) : ClassName \
752 { \
753 void test(); \
754 }; \
755 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)(&INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)::test, #ClassName, Catch::NameAndDesc(TestName, Desc), CATCH_INTERNAL_LINEINFO); \
756 } \
757 void INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____)::test()
758
759 ///////////////////////////////////////////////////////////////////////////////
760 #define INTERNAL_CATCH_REGISTER_TESTCASE(Function, Name, Desc) \
761 Catch::AutoReg(Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc(Name, Desc));
762 #endif
763
764 // #included from: internal/catch_capture.hpp
765 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
766
767 // #included from: catch_result_builder.h
768 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
769
770 // #included from: catch_result_type.h
771 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
772
773 namespace Catch {
774
775 // ResultWas::OfType enum
776 struct ResultWas
777 {
778 enum OfType
779 {
780 Unknown = -1,
781 Ok = 0,
782 Info = 1,
783 Warning = 2,
784
785 FailureBit = 0x10,
786
787 ExpressionFailed = FailureBit | 1,
788 ExplicitFailure = FailureBit | 2,
789
790 Exception = 0x100 | FailureBit,
791
792 ThrewException = Exception | 1,
793 DidntThrowException = Exception | 2,
794
795 FatalErrorCondition = 0x200 | FailureBit
796
797 };
798 };
799
isOk(ResultWas::OfType resultType)800 inline bool isOk(ResultWas::OfType resultType)
801 {
802 return (resultType & ResultWas::FailureBit) == 0;
803 }
isJustInfo(int flags)804 inline bool isJustInfo(int flags)
805 {
806 return flags == ResultWas::Info;
807 }
808
809 // ResultDisposition::Flags enum
810 struct ResultDisposition
811 {
812 enum Flags
813 {
814 Normal = 0x01,
815
816 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
817 FalseTest = 0x04, // Prefix expression with !
818 SuppressFail = 0x08 // Failures are reported but do not fail the test
819 };
820 };
821
operator |(ResultDisposition::Flags lhs,ResultDisposition::Flags rhs)822 inline ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs)
823 {
824 return static_cast<ResultDisposition::Flags>(static_cast<int>(lhs) | static_cast<int>(rhs));
825 }
826
shouldContinueOnFailure(int flags)827 inline bool shouldContinueOnFailure(int flags) { return (flags & ResultDisposition::ContinueOnFailure) != 0; }
isFalseTest(int flags)828 inline bool isFalseTest(int flags) { return (flags & ResultDisposition::FalseTest) != 0; }
shouldSuppressFailure(int flags)829 inline bool shouldSuppressFailure(int flags) { return (flags & ResultDisposition::SuppressFail) != 0; }
830
831 } // end namespace Catch
832
833 // #included from: catch_assertionresult.h
834 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
835
836 #include <string>
837
838 namespace Catch {
839
840 struct AssertionInfo
841 {
AssertionInfoCatch::AssertionInfo842 AssertionInfo() {}
843 AssertionInfo(std::string const& _macroName,
844 SourceLineInfo const& _lineInfo,
845 std::string const& _capturedExpression,
846 ResultDisposition::Flags _resultDisposition);
847
848 std::string macroName;
849 SourceLineInfo lineInfo;
850 std::string capturedExpression;
851 ResultDisposition::Flags resultDisposition;
852 };
853
854 struct AssertionResultData
855 {
AssertionResultDataCatch::AssertionResultData856 AssertionResultData() : resultType(ResultWas::Unknown) {}
857
858 std::string reconstructedExpression;
859 std::string message;
860 ResultWas::OfType resultType;
861 };
862
863 class AssertionResult
864 {
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>
905 class AllOf;
906 template <typename ExpressionT>
907 class AnyOf;
908 template <typename ExpressionT>
909 class Not;
910 }
911
912 template <typename ExpressionT>
913 struct Matcher : SharedImpl<IShared>
914 {
915 typedef ExpressionT ExpressionType;
916
~MatcherCatch::Matchers::Impl::Matcher917 virtual ~Matcher() {}
918 virtual Ptr<Matcher> clone() const = 0;
919 virtual bool match(ExpressionT const& expr) const = 0;
920 virtual std::string toString() const = 0;
921
922 Generic::AllOf<ExpressionT> operator&&(Matcher<ExpressionT> const& other) const;
923 Generic::AnyOf<ExpressionT> operator||(Matcher<ExpressionT> const& other) const;
924 Generic::Not<ExpressionT> operator!() const;
925 };
926
927 template <typename DerivedT, typename ExpressionT>
928 struct MatcherImpl : Matcher<ExpressionT>
929 {
930
cloneCatch::Matchers::Impl::MatcherImpl931 virtual Ptr<Matcher<ExpressionT>> clone() const
932 {
933 return Ptr<Matcher<ExpressionT>>(new DerivedT(static_cast<DerivedT const&>(*this)));
934 }
935 };
936
937 namespace Generic {
938 template <typename ExpressionT>
939 class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT>
940 {
941 public:
Not(Matcher<ExpressionT> const & matcher)942 explicit Not(Matcher<ExpressionT> const& matcher) : m_matcher(matcher.clone()) {}
Not(Not const & other)943 Not(Not const& other) : m_matcher(other.m_matcher) {}
944
match(ExpressionT const & expr) const945 virtual bool match(ExpressionT const& expr) const CATCH_OVERRIDE
946 {
947 return !m_matcher->match(expr);
948 }
949
toString() const950 virtual std::string toString() const CATCH_OVERRIDE
951 {
952 return "not " + m_matcher->toString();
953 }
954
955 private:
956 Ptr<Matcher<ExpressionT>> m_matcher;
957 };
958
959 template <typename ExpressionT>
960 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT>
961 {
962 public:
AllOf()963 AllOf() {}
AllOf(AllOf const & other)964 AllOf(AllOf const& other) : m_matchers(other.m_matchers) {}
965
add(Matcher<ExpressionT> const & matcher)966 AllOf& add(Matcher<ExpressionT> const& matcher)
967 {
968 m_matchers.push_back(matcher.clone());
969 return *this;
970 }
match(ExpressionT const & expr) const971 virtual bool match(ExpressionT const& expr) const
972 {
973 for (std::size_t i = 0; i < m_matchers.size(); ++i)
974 if (!m_matchers[i]->match(expr))
975 return false;
976 return true;
977 }
toString() const978 virtual std::string toString() const
979 {
980 std::ostringstream oss;
981 oss << "( ";
982 for (std::size_t i = 0; i < m_matchers.size(); ++i)
983 {
984 if (i != 0)
985 oss << " and ";
986 oss << m_matchers[i]->toString();
987 }
988 oss << " )";
989 return oss.str();
990 }
991
operator &&(Matcher<ExpressionT> const & other) const992 AllOf operator&&(Matcher<ExpressionT> const& other) const
993 {
994 AllOf allOfExpr(*this);
995 allOfExpr.add(other);
996 return allOfExpr;
997 }
998
999 private:
1000 std::vector<Ptr<Matcher<ExpressionT>>> m_matchers;
1001 };
1002
1003 template <typename ExpressionT>
1004 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT>
1005 {
1006 public:
AnyOf()1007 AnyOf() {}
AnyOf(AnyOf const & other)1008 AnyOf(AnyOf const& other) : m_matchers(other.m_matchers) {}
1009
add(Matcher<ExpressionT> const & matcher)1010 AnyOf& add(Matcher<ExpressionT> const& matcher)
1011 {
1012 m_matchers.push_back(matcher.clone());
1013 return *this;
1014 }
match(ExpressionT const & expr) const1015 virtual bool match(ExpressionT const& expr) const
1016 {
1017 for (std::size_t i = 0; i < m_matchers.size(); ++i)
1018 if (m_matchers[i]->match(expr))
1019 return true;
1020 return false;
1021 }
toString() const1022 virtual std::string toString() const
1023 {
1024 std::ostringstream oss;
1025 oss << "( ";
1026 for (std::size_t i = 0; i < m_matchers.size(); ++i)
1027 {
1028 if (i != 0)
1029 oss << " or ";
1030 oss << m_matchers[i]->toString();
1031 }
1032 oss << " )";
1033 return oss.str();
1034 }
1035
operator ||(Matcher<ExpressionT> const & other) const1036 AnyOf operator||(Matcher<ExpressionT> const& other) const
1037 {
1038 AnyOf anyOfExpr(*this);
1039 anyOfExpr.add(other);
1040 return anyOfExpr;
1041 }
1042
1043 private:
1044 std::vector<Ptr<Matcher<ExpressionT>>> m_matchers;
1045 };
1046
1047 } // namespace Generic
1048
1049 template <typename ExpressionT>
operator &&(Matcher<ExpressionT> const & other) const1050 Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator&&(Matcher<ExpressionT> const& other) const
1051 {
1052 Generic::AllOf<ExpressionT> allOfExpr;
1053 allOfExpr.add(*this);
1054 allOfExpr.add(other);
1055 return allOfExpr;
1056 }
1057
1058 template <typename ExpressionT>
operator ||(Matcher<ExpressionT> const & other) const1059 Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator||(Matcher<ExpressionT> const& other) const
1060 {
1061 Generic::AnyOf<ExpressionT> anyOfExpr;
1062 anyOfExpr.add(*this);
1063 anyOfExpr.add(other);
1064 return anyOfExpr;
1065 }
1066
1067 template <typename ExpressionT>
operator !() const1068 Generic::Not<ExpressionT> Matcher<ExpressionT>::operator!() const
1069 {
1070 return Generic::Not<ExpressionT>(*this);
1071 }
1072
1073 namespace StdString {
1074
makeString(std::string const & str)1075 inline std::string makeString(std::string const& str) { return str; }
makeString(const char * str)1076 inline std::string makeString(const char* str) { return str ? std::string(str) : std::string(); }
1077
1078 struct CasedString
1079 {
CasedStringCatch::Matchers::Impl::StdString::CasedString1080 CasedString(std::string const& str, CaseSensitive::Choice caseSensitivity)
1081 : m_caseSensitivity(caseSensitivity),
1082 m_str(adjustString(str))
1083 {
1084 }
adjustStringCatch::Matchers::Impl::StdString::CasedString1085 std::string adjustString(std::string const& str) const
1086 {
1087 return m_caseSensitivity == CaseSensitive::No
1088 ? toLower(str)
1089 : str;
1090 }
toStringSuffixCatch::Matchers::Impl::StdString::CasedString1091 std::string toStringSuffix() const
1092 {
1093 return m_caseSensitivity == CaseSensitive::No
1094 ? " (case insensitive)"
1095 : "";
1096 }
1097 CaseSensitive::Choice m_caseSensitivity;
1098 std::string m_str;
1099 };
1100
1101 struct Equals : MatcherImpl<Equals, std::string>
1102 {
EqualsCatch::Matchers::Impl::StdString::Equals1103 Equals(std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
1104 : m_data(str, caseSensitivity)
1105 {
1106 }
EqualsCatch::Matchers::Impl::StdString::Equals1107 Equals(Equals const& other) : m_data(other.m_data) {}
1108
1109 virtual ~Equals();
1110
matchCatch::Matchers::Impl::StdString::Equals1111 virtual bool match(std::string const& expr) const
1112 {
1113 return m_data.m_str == m_data.adjustString(expr);
1114 ;
1115 }
toStringCatch::Matchers::Impl::StdString::Equals1116 virtual std::string toString() const
1117 {
1118 return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1119 }
1120
1121 CasedString m_data;
1122 };
1123
1124 struct Contains : MatcherImpl<Contains, std::string>
1125 {
ContainsCatch::Matchers::Impl::StdString::Contains1126 Contains(std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
1127 : m_data(substr, caseSensitivity) {}
ContainsCatch::Matchers::Impl::StdString::Contains1128 Contains(Contains const& other) : m_data(other.m_data) {}
1129
1130 virtual ~Contains();
1131
matchCatch::Matchers::Impl::StdString::Contains1132 virtual bool match(std::string const& expr) const
1133 {
1134 return m_data.adjustString(expr).find(m_data.m_str) != std::string::npos;
1135 }
toStringCatch::Matchers::Impl::StdString::Contains1136 virtual std::string toString() const
1137 {
1138 return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1139 }
1140
1141 CasedString m_data;
1142 };
1143
1144 struct StartsWith : MatcherImpl<StartsWith, std::string>
1145 {
StartsWithCatch::Matchers::Impl::StdString::StartsWith1146 StartsWith(std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
1147 : m_data(substr, caseSensitivity) {}
1148
StartsWithCatch::Matchers::Impl::StdString::StartsWith1149 StartsWith(StartsWith const& other) : m_data(other.m_data) {}
1150
1151 virtual ~StartsWith();
1152
matchCatch::Matchers::Impl::StdString::StartsWith1153 virtual bool match(std::string const& expr) const
1154 {
1155 return m_data.adjustString(expr).find(m_data.m_str) == 0;
1156 }
toStringCatch::Matchers::Impl::StdString::StartsWith1157 virtual std::string toString() const
1158 {
1159 return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1160 }
1161
1162 CasedString m_data;
1163 };
1164
1165 struct EndsWith : MatcherImpl<EndsWith, std::string>
1166 {
EndsWithCatch::Matchers::Impl::StdString::EndsWith1167 EndsWith(std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
1168 : m_data(substr, caseSensitivity) {}
EndsWithCatch::Matchers::Impl::StdString::EndsWith1169 EndsWith(EndsWith const& other) : m_data(other.m_data) {}
1170
1171 virtual ~EndsWith();
1172
matchCatch::Matchers::Impl::StdString::EndsWith1173 virtual bool match(std::string const& expr) const
1174 {
1175 return m_data.adjustString(expr).find(m_data.m_str) == expr.size() - m_data.m_str.size();
1176 }
toStringCatch::Matchers::Impl::StdString::EndsWith1177 virtual std::string toString() const
1178 {
1179 return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1180 }
1181
1182 CasedString m_data;
1183 };
1184 } // namespace StdString
1185 } // namespace Impl
1186
1187 // The following functions create the actual matcher objects.
1188 // This allows the types to be inferred
1189 template <typename ExpressionT>
Not(Impl::Matcher<ExpressionT> const & m)1190 inline Impl::Generic::Not<ExpressionT> Not(Impl::Matcher<ExpressionT> const& m)
1191 {
1192 return Impl::Generic::Not<ExpressionT>(m);
1193 }
1194
1195 template <typename ExpressionT>
AllOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2)1196 inline Impl::Generic::AllOf<ExpressionT> AllOf(Impl::Matcher<ExpressionT> const& m1,
1197 Impl::Matcher<ExpressionT> const& m2)
1198 {
1199 return Impl::Generic::AllOf<ExpressionT>().add(m1).add(m2);
1200 }
1201 template <typename ExpressionT>
AllOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2,Impl::Matcher<ExpressionT> const & m3)1202 inline Impl::Generic::AllOf<ExpressionT> AllOf(Impl::Matcher<ExpressionT> const& m1,
1203 Impl::Matcher<ExpressionT> const& m2,
1204 Impl::Matcher<ExpressionT> const& m3)
1205 {
1206 return Impl::Generic::AllOf<ExpressionT>().add(m1).add(m2).add(m3);
1207 }
1208 template <typename ExpressionT>
AnyOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2)1209 inline Impl::Generic::AnyOf<ExpressionT> AnyOf(Impl::Matcher<ExpressionT> const& m1,
1210 Impl::Matcher<ExpressionT> const& m2)
1211 {
1212 return Impl::Generic::AnyOf<ExpressionT>().add(m1).add(m2);
1213 }
1214 template <typename ExpressionT>
AnyOf(Impl::Matcher<ExpressionT> const & m1,Impl::Matcher<ExpressionT> const & m2,Impl::Matcher<ExpressionT> const & m3)1215 inline Impl::Generic::AnyOf<ExpressionT> AnyOf(Impl::Matcher<ExpressionT> const& m1,
1216 Impl::Matcher<ExpressionT> const& m2,
1217 Impl::Matcher<ExpressionT> const& m3)
1218 {
1219 return Impl::Generic::AnyOf<ExpressionT>().add(m1).add(m2).add(m3);
1220 }
1221
Equals(std::string const & str,CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)1222 inline Impl::StdString::Equals Equals(std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
1223 {
1224 return Impl::StdString::Equals(str, caseSensitivity);
1225 }
Equals(const char * str,CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)1226 inline Impl::StdString::Equals Equals(const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
1227 {
1228 return Impl::StdString::Equals(Impl::StdString::makeString(str), caseSensitivity);
1229 }
Contains(std::string const & substr,CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)1230 inline Impl::StdString::Contains Contains(std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
1231 {
1232 return Impl::StdString::Contains(substr, caseSensitivity);
1233 }
Contains(const char * substr,CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)1234 inline Impl::StdString::Contains Contains(const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)
1235 {
1236 return Impl::StdString::Contains(Impl::StdString::makeString(substr), caseSensitivity);
1237 }
StartsWith(std::string const & substr)1238 inline Impl::StdString::StartsWith StartsWith(std::string const& substr)
1239 {
1240 return Impl::StdString::StartsWith(substr);
1241 }
StartsWith(const char * substr)1242 inline Impl::StdString::StartsWith StartsWith(const char* substr)
1243 {
1244 return Impl::StdString::StartsWith(Impl::StdString::makeString(substr));
1245 }
EndsWith(std::string const & substr)1246 inline Impl::StdString::EndsWith EndsWith(std::string const& substr)
1247 {
1248 return Impl::StdString::EndsWith(substr);
1249 }
EndsWith(const char * substr)1250 inline Impl::StdString::EndsWith EndsWith(const char* substr)
1251 {
1252 return Impl::StdString::EndsWith(Impl::StdString::makeString(substr));
1253 }
1254
1255 } // namespace Matchers
1256
1257 using namespace Matchers;
1258
1259 } // namespace Catch
1260
1261 namespace Catch {
1262
1263 struct TestFailureException
1264 {
1265 };
1266
1267 template <typename T>
1268 class ExpressionLhs;
1269
1270 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1271
1272 struct CopyableStream
1273 {
CopyableStreamCatch::CopyableStream1274 CopyableStream() {}
CopyableStreamCatch::CopyableStream1275 CopyableStream(CopyableStream const& other)
1276 {
1277 oss << other.oss.str();
1278 }
operator =Catch::CopyableStream1279 CopyableStream& operator=(CopyableStream const& other)
1280 {
1281 oss.str("");
1282 oss << other.oss.str();
1283 return *this;
1284 }
1285 std::ostringstream oss;
1286 };
1287
1288 class ResultBuilder
1289 {
1290 public:
1291 ResultBuilder(char const* macroName,
1292 SourceLineInfo const& lineInfo,
1293 char const* capturedExpression,
1294 ResultDisposition::Flags resultDisposition,
1295 char const* secondArg = "");
1296
1297 template <typename T>
1298 ExpressionLhs<T const&> operator<=(T const& operand);
1299 ExpressionLhs<bool> operator<=(bool value);
1300
1301 template <typename T>
operator <<(T const & value)1302 ResultBuilder& operator<<(T const& value)
1303 {
1304 m_stream.oss << value;
1305 return *this;
1306 }
1307
1308 template <typename RhsT>
1309 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator&&(RhsT const&);
1310 template <typename RhsT>
1311 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator||(RhsT const&);
1312
1313 ResultBuilder& setResultType(ResultWas::OfType result);
1314 ResultBuilder& setResultType(bool result);
1315 ResultBuilder& setLhs(std::string const& lhs);
1316 ResultBuilder& setRhs(std::string const& rhs);
1317 ResultBuilder& setOp(std::string const& op);
1318
1319 void endExpression();
1320
1321 std::string reconstructExpression() const;
1322 AssertionResult build() const;
1323
1324 void useActiveException(ResultDisposition::Flags resultDisposition = ResultDisposition::Normal);
1325 void captureResult(ResultWas::OfType resultType);
1326 void captureExpression();
1327 void captureExpectedException(std::string const& expectedMessage);
1328 void captureExpectedException(Matchers::Impl::Matcher<std::string> const& matcher);
1329 void handleResult(AssertionResult const& result);
1330 void react();
1331 bool shouldDebugBreak() const;
1332 bool allowThrows() const;
1333
1334 private:
1335 AssertionInfo m_assertionInfo;
1336 AssertionResultData m_data;
1337 struct ExprComponents
1338 {
ExprComponentsCatch::ResultBuilder::ExprComponents1339 ExprComponents() : testFalse(false) {}
1340 bool testFalse;
1341 std::string lhs, rhs, op;
1342 } m_exprComponents;
1343 CopyableStream m_stream;
1344
1345 bool m_shouldDebugBreak;
1346 bool m_shouldThrow;
1347 };
1348
1349 } // namespace Catch
1350
1351 // Include after due to circular dependency:
1352 // #included from: catch_expression_lhs.hpp
1353 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1354
1355 // #included from: catch_evaluate.hpp
1356 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
1357
1358 #ifdef _MSC_VER
1359 #pragma warning(push)
1360 #pragma warning(disable : 4389) // '==' : signed/unsigned mismatch
1361 #endif
1362
1363 #include <cstddef>
1364
1365 namespace Catch {
1366 namespace Internal {
1367
1368 enum Operator
1369 {
1370 IsEqualTo,
1371 IsNotEqualTo,
1372 IsLessThan,
1373 IsGreaterThan,
1374 IsLessThanOrEqualTo,
1375 IsGreaterThanOrEqualTo
1376 };
1377
1378 template <Operator Op>
1379 struct OperatorTraits
1380 {
getNameCatch::Internal::OperatorTraits1381 static const char* getName() { return "*error*"; }
1382 };
1383 template <>
1384 struct OperatorTraits<IsEqualTo>
1385 {
getNameCatch::Internal::OperatorTraits1386 static const char* getName() { return "=="; }
1387 };
1388 template <>
1389 struct OperatorTraits<IsNotEqualTo>
1390 {
getNameCatch::Internal::OperatorTraits1391 static const char* getName() { return "!="; }
1392 };
1393 template <>
1394 struct OperatorTraits<IsLessThan>
1395 {
getNameCatch::Internal::OperatorTraits1396 static const char* getName() { return "<"; }
1397 };
1398 template <>
1399 struct OperatorTraits<IsGreaterThan>
1400 {
getNameCatch::Internal::OperatorTraits1401 static const char* getName() { return ">"; }
1402 };
1403 template <>
1404 struct OperatorTraits<IsLessThanOrEqualTo>
1405 {
getNameCatch::Internal::OperatorTraits1406 static const char* getName() { return "<="; }
1407 };
1408 template <>
1409 struct OperatorTraits<IsGreaterThanOrEqualTo>
1410 {
getNameCatch::Internal::OperatorTraits1411 static const char* getName() { return ">="; }
1412 };
1413
1414 template <typename T>
opCast(T const & t)1415 inline T& opCast(T const& t)
1416 {
1417 return const_cast<T&>(t);
1418 }
1419
1420 // nullptr_t support based on pull request #154 from Konstantin Baumann
1421 #ifdef CATCH_CONFIG_CPP11_NULLPTR
opCast(std::nullptr_t)1422 inline std::nullptr_t opCast(std::nullptr_t)
1423 {
1424 return nullptr;
1425 }
1426 #endif // CATCH_CONFIG_CPP11_NULLPTR
1427
1428 // So the compare overloads can be operator agnostic we convey the operator as a template
1429 // enum, which is used to specialise an Evaluator for doing the comparison.
1430 template <typename T1, typename T2, Operator Op>
1431 class Evaluator
1432 {
1433 };
1434
1435 template <typename T1, typename T2>
1436 struct Evaluator<T1, T2, IsEqualTo>
1437 {
evaluateCatch::Internal::Evaluator1438 static bool evaluate(T1 const& lhs, T2 const& rhs)
1439 {
1440 return opCast(lhs) == opCast(rhs);
1441 }
1442 };
1443 template <typename T1, typename T2>
1444 struct Evaluator<T1, T2, IsNotEqualTo>
1445 {
evaluateCatch::Internal::Evaluator1446 static bool evaluate(T1 const& lhs, T2 const& rhs)
1447 {
1448 return opCast(lhs) != opCast(rhs);
1449 }
1450 };
1451 template <typename T1, typename T2>
1452 struct Evaluator<T1, T2, IsLessThan>
1453 {
evaluateCatch::Internal::Evaluator1454 static bool evaluate(T1 const& lhs, T2 const& rhs)
1455 {
1456 return opCast(lhs) < opCast(rhs);
1457 }
1458 };
1459 template <typename T1, typename T2>
1460 struct Evaluator<T1, T2, IsGreaterThan>
1461 {
evaluateCatch::Internal::Evaluator1462 static bool evaluate(T1 const& lhs, T2 const& rhs)
1463 {
1464 return opCast(lhs) > opCast(rhs);
1465 }
1466 };
1467 template <typename T1, typename T2>
1468 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo>
1469 {
evaluateCatch::Internal::Evaluator1470 static bool evaluate(T1 const& lhs, T2 const& rhs)
1471 {
1472 return opCast(lhs) >= opCast(rhs);
1473 }
1474 };
1475 template <typename T1, typename T2>
1476 struct Evaluator<T1, T2, IsLessThanOrEqualTo>
1477 {
evaluateCatch::Internal::Evaluator1478 static bool evaluate(T1 const& lhs, T2 const& rhs)
1479 {
1480 return opCast(lhs) <= opCast(rhs);
1481 }
1482 };
1483
1484 template <Operator Op, typename T1, typename T2>
applyEvaluator(T1 const & lhs,T2 const & rhs)1485 bool applyEvaluator(T1 const& lhs, T2 const& rhs)
1486 {
1487 return Evaluator<T1, T2, Op>::evaluate(lhs, rhs);
1488 }
1489
1490 // This level of indirection allows us to specialise for integer types
1491 // to avoid signed/ unsigned warnings
1492
1493 // "base" overload
1494 template <Operator Op, typename T1, typename T2>
compare(T1 const & lhs,T2 const & rhs)1495 bool compare(T1 const& lhs, T2 const& rhs)
1496 {
1497 return Evaluator<T1, T2, Op>::evaluate(lhs, rhs);
1498 }
1499
1500 // unsigned X to int
1501 template <Operator Op>
compare(unsigned int lhs,int rhs)1502 bool compare(unsigned int lhs, int rhs)
1503 {
1504 return applyEvaluator<Op>(lhs, static_cast<unsigned int>(rhs));
1505 }
1506 template <Operator Op>
compare(unsigned long lhs,int rhs)1507 bool compare(unsigned long lhs, int rhs)
1508 {
1509 return applyEvaluator<Op>(lhs, static_cast<unsigned int>(rhs));
1510 }
1511 template <Operator Op>
compare(unsigned char lhs,int rhs)1512 bool compare(unsigned char lhs, int rhs)
1513 {
1514 return applyEvaluator<Op>(lhs, static_cast<unsigned int>(rhs));
1515 }
1516
1517 // unsigned X to long
1518 template <Operator Op>
compare(unsigned int lhs,long rhs)1519 bool compare(unsigned int lhs, long rhs)
1520 {
1521 return applyEvaluator<Op>(lhs, static_cast<unsigned long>(rhs));
1522 }
1523 template <Operator Op>
compare(unsigned long lhs,long rhs)1524 bool compare(unsigned long lhs, long rhs)
1525 {
1526 return applyEvaluator<Op>(lhs, static_cast<unsigned long>(rhs));
1527 }
1528 template <Operator Op>
compare(unsigned char lhs,long rhs)1529 bool compare(unsigned char lhs, long rhs)
1530 {
1531 return applyEvaluator<Op>(lhs, static_cast<unsigned long>(rhs));
1532 }
1533
1534 // int to unsigned X
1535 template <Operator Op>
compare(int lhs,unsigned int rhs)1536 bool compare(int lhs, unsigned int rhs)
1537 {
1538 return applyEvaluator<Op>(static_cast<unsigned int>(lhs), rhs);
1539 }
1540 template <Operator Op>
compare(int lhs,unsigned long rhs)1541 bool compare(int lhs, unsigned long rhs)
1542 {
1543 return applyEvaluator<Op>(static_cast<unsigned int>(lhs), rhs);
1544 }
1545 template <Operator Op>
compare(int lhs,unsigned char rhs)1546 bool compare(int lhs, unsigned char rhs)
1547 {
1548 return applyEvaluator<Op>(static_cast<unsigned int>(lhs), rhs);
1549 }
1550
1551 // long to unsigned X
1552 template <Operator Op>
compare(long lhs,unsigned int rhs)1553 bool compare(long lhs, unsigned int rhs)
1554 {
1555 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1556 }
1557 template <Operator Op>
compare(long lhs,unsigned long rhs)1558 bool compare(long lhs, unsigned long rhs)
1559 {
1560 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1561 }
1562 template <Operator Op>
compare(long lhs,unsigned char rhs)1563 bool compare(long lhs, unsigned char rhs)
1564 {
1565 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1566 }
1567
1568 // pointer to long (when comparing against NULL)
1569 template <Operator Op, typename T>
compare(long lhs,T * rhs)1570 bool compare(long lhs, T* rhs)
1571 {
1572 return Evaluator<T*, T*, Op>::evaluate(reinterpret_cast<T*>(lhs), rhs);
1573 }
1574 template <Operator Op, typename T>
compare(T * lhs,long rhs)1575 bool compare(T* lhs, long rhs)
1576 {
1577 return Evaluator<T*, T*, Op>::evaluate(lhs, reinterpret_cast<T*>(rhs));
1578 }
1579
1580 // pointer to int (when comparing against NULL)
1581 template <Operator Op, typename T>
compare(int lhs,T * rhs)1582 bool compare(int lhs, T* rhs)
1583 {
1584 return Evaluator<T*, T*, Op>::evaluate(reinterpret_cast<T*>(lhs), rhs);
1585 }
1586 template <Operator Op, typename T>
compare(T * lhs,int rhs)1587 bool compare(T* lhs, int rhs)
1588 {
1589 return Evaluator<T*, T*, Op>::evaluate(lhs, reinterpret_cast<T*>(rhs));
1590 }
1591
1592 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1593 // long long to unsigned X
1594 template <Operator Op>
compare(long long lhs,unsigned int rhs)1595 bool compare(long long lhs, unsigned int rhs)
1596 {
1597 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1598 }
1599 template <Operator Op>
compare(long long lhs,unsigned long rhs)1600 bool compare(long long lhs, unsigned long rhs)
1601 {
1602 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1603 }
1604 template <Operator Op>
compare(long long lhs,unsigned long long rhs)1605 bool compare(long long lhs, unsigned long long rhs)
1606 {
1607 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1608 }
1609 template <Operator Op>
compare(long long lhs,unsigned char rhs)1610 bool compare(long long lhs, unsigned char rhs)
1611 {
1612 return applyEvaluator<Op>(static_cast<unsigned long>(lhs), rhs);
1613 }
1614
1615 // unsigned long long to X
1616 template <Operator Op>
compare(unsigned long long lhs,int rhs)1617 bool compare(unsigned long long lhs, int rhs)
1618 {
1619 return applyEvaluator<Op>(static_cast<long>(lhs), rhs);
1620 }
1621 template <Operator Op>
compare(unsigned long long lhs,long rhs)1622 bool compare(unsigned long long lhs, long rhs)
1623 {
1624 return applyEvaluator<Op>(static_cast<long>(lhs), rhs);
1625 }
1626 template <Operator Op>
compare(unsigned long long lhs,long long rhs)1627 bool compare(unsigned long long lhs, long long rhs)
1628 {
1629 return applyEvaluator<Op>(static_cast<long>(lhs), rhs);
1630 }
1631 template <Operator Op>
compare(unsigned long long lhs,char rhs)1632 bool compare(unsigned long long lhs, char rhs)
1633 {
1634 return applyEvaluator<Op>(static_cast<long>(lhs), rhs);
1635 }
1636
1637 // pointer to long long (when comparing against NULL)
1638 template <Operator Op, typename T>
compare(long long lhs,T * rhs)1639 bool compare(long long lhs, T* rhs)
1640 {
1641 return Evaluator<T*, T*, Op>::evaluate(reinterpret_cast<T*>(lhs), rhs);
1642 }
1643 template <Operator Op, typename T>
compare(T * lhs,long long rhs)1644 bool compare(T* lhs, long long rhs)
1645 {
1646 return Evaluator<T*, T*, Op>::evaluate(lhs, reinterpret_cast<T*>(rhs));
1647 }
1648 #endif // CATCH_CONFIG_CPP11_LONG_LONG
1649
1650 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1651 // pointer to nullptr_t (when comparing against nullptr)
1652 template <Operator Op, typename T>
compare(std::nullptr_t,T * rhs)1653 bool compare(std::nullptr_t, T* rhs)
1654 {
1655 return Evaluator<T*, T*, Op>::evaluate(nullptr, rhs);
1656 }
1657 template <Operator Op, typename T>
compare(T * lhs,std::nullptr_t)1658 bool compare(T* lhs, std::nullptr_t)
1659 {
1660 return Evaluator<T*, T*, Op>::evaluate(lhs, nullptr);
1661 }
1662 #endif // CATCH_CONFIG_CPP11_NULLPTR
1663
1664 } // end of namespace Internal
1665 } // end of namespace Catch
1666
1667 #ifdef _MSC_VER
1668 #pragma warning(pop)
1669 #endif
1670
1671 // #included from: catch_tostring.h
1672 #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1673
1674 #include <cstddef>
1675 #include <iomanip>
1676 #include <limits>
1677 #include <sstream>
1678 #include <vector>
1679
1680 #ifdef __OBJC__
1681 // #included from: catch_objc_arc.hpp
1682 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1683
1684 #import <Foundation/Foundation.h>
1685
1686 #ifdef __has_feature
1687 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
1688 #else
1689 #define CATCH_ARC_ENABLED 0
1690 #endif
1691
1692 void arcSafeRelease(NSObject* obj);
1693 id performOptionalSelector(id obj, SEL sel);
1694
1695 #if !CATCH_ARC_ENABLED
arcSafeRelease(NSObject * obj)1696 inline void arcSafeRelease(NSObject* obj)
1697 {
1698 [obj release];
1699 }
performOptionalSelector(id obj,SEL sel)1700 inline id performOptionalSelector(id obj, SEL sel)
1701 {
1702 if ([obj respondsToSelector:sel])
1703 return [obj performSelector:sel];
1704 return nil;
1705 }
1706 #define CATCH_UNSAFE_UNRETAINED
1707 #define CATCH_ARC_STRONG
1708 #else
arcSafeRelease(NSObject *)1709 inline void arcSafeRelease(NSObject*)
1710 {
1711 }
performOptionalSelector(id obj,SEL sel)1712 inline id performOptionalSelector(id obj, SEL sel)
1713 {
1714 #ifdef __clang__
1715 #pragma clang diagnostic push
1716 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1717 #endif
1718 if ([obj respondsToSelector:sel])
1719 return [obj performSelector:sel];
1720 #ifdef __clang__
1721 #pragma clang diagnostic pop
1722 #endif
1723 return nil;
1724 }
1725 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1726 #define CATCH_ARC_STRONG __strong
1727 #endif
1728
1729 #endif
1730
1731 #ifdef CATCH_CONFIG_CPP11_TUPLE
1732 #include <tuple>
1733 #endif
1734
1735 #ifdef CATCH_CONFIG_CPP11_IS_ENUM
1736 #include <type_traits>
1737 #endif
1738
1739 namespace Catch {
1740
1741 // Why we're here.
1742 template <typename T>
1743 std::string toString(T const& value);
1744
1745 // Built in overloads
1746
1747 std::string toString(std::string const& value);
1748 std::string toString(std::wstring const& value);
1749 std::string toString(const char* const value);
1750 std::string toString(char* const value);
1751 std::string toString(const wchar_t* const value);
1752 std::string toString(wchar_t* const value);
1753 std::string toString(int value);
1754 std::string toString(unsigned long value);
1755 std::string toString(unsigned int value);
1756 std::string toString(const double value);
1757 std::string toString(const float value);
1758 std::string toString(bool value);
1759 std::string toString(char value);
1760 std::string toString(signed char value);
1761 std::string toString(unsigned char value);
1762
1763 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1764 std::string toString(long long value);
1765 std::string toString(unsigned long long value);
1766 #endif
1767
1768 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1769 std::string toString(std::nullptr_t);
1770 #endif
1771
1772 #ifdef __OBJC__
1773 std::string toString(NSString const* const& nsstring);
1774 std::string toString(NSString* CATCH_ARC_STRONG const& nsstring);
1775 std::string toString(NSObject* const& nsObject);
1776 #endif
1777
1778 namespace Detail {
1779
1780 extern const std::string unprintableString;
1781
1782 struct BorgType
1783 {
1784 template <typename T>
1785 BorgType(T const&);
1786 };
1787
1788 struct TrueType
1789 {
1790 char sizer[1];
1791 };
1792 struct FalseType
1793 {
1794 char sizer[2];
1795 };
1796
1797 TrueType& testStreamable(std::ostream&);
1798 FalseType testStreamable(FalseType);
1799
1800 FalseType operator<<(std::ostream const&, BorgType const&);
1801
1802 template <typename T>
1803 struct IsStreamInsertable
1804 {
1805 static std::ostream& s;
1806 static T const& t;
1807 enum
1808 {
1809 value = sizeof(testStreamable(s << t)) == sizeof(TrueType)
1810 };
1811 };
1812
1813 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1814 template <typename T,
1815 bool IsEnum = std::is_enum<T>::value>
1816 struct EnumStringMaker
1817 {
convertCatch::Detail::EnumStringMaker1818 static std::string convert(T const&) { return unprintableString; }
1819 };
1820
1821 template <typename T>
1822 struct EnumStringMaker<T, true>
1823 {
convertCatch::Detail::EnumStringMaker1824 static std::string convert(T const& v)
1825 {
1826 return ::Catch::toString(
1827 static_cast<typename std::underlying_type<T>::type>(v));
1828 }
1829 };
1830 #endif
1831 template <bool C>
1832 struct StringMakerBase
1833 {
1834 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1835 template <typename T>
convertCatch::Detail::StringMakerBase1836 static std::string convert(T const& v)
1837 {
1838 return EnumStringMaker<T>::convert(v);
1839 }
1840 #else
1841 template <typename T>
1842 static std::string convert(T const&)
1843 {
1844 return unprintableString;
1845 }
1846 #endif
1847 };
1848
1849 template <>
1850 struct StringMakerBase<true>
1851 {
1852 template <typename T>
convertCatch::Detail::StringMakerBase1853 static std::string convert(T const& _value)
1854 {
1855 std::ostringstream oss;
1856 oss << _value;
1857 return oss.str();
1858 }
1859 };
1860
1861 std::string rawMemoryToString(const void* object, std::size_t size);
1862
1863 template <typename T>
rawMemoryToString(const T & object)1864 inline std::string rawMemoryToString(const T& object)
1865 {
1866 return rawMemoryToString(&object, sizeof(object));
1867 }
1868
1869 } // end namespace Detail
1870
1871 template <typename T>
1872 struct StringMaker : Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value>
1873 {
1874 };
1875
1876 template <typename T>
1877 struct StringMaker<T*>
1878 {
1879 template <typename U>
convertCatch::StringMaker1880 static std::string convert(U* p)
1881 {
1882 if (!p)
1883 return "NULL";
1884 else
1885 return Detail::rawMemoryToString(p);
1886 }
1887 };
1888
1889 template <typename R, typename C>
1890 struct StringMaker<R C::*>
1891 {
convertCatch::StringMaker1892 static std::string convert(R C::*p)
1893 {
1894 if (!p)
1895 return "NULL";
1896 else
1897 return Detail::rawMemoryToString(p);
1898 }
1899 };
1900
1901 namespace Detail {
1902 template <typename InputIterator>
1903 std::string rangeToString(InputIterator first, InputIterator last);
1904 }
1905
1906 //template<typename T, typename Allocator>
1907 //struct StringMaker<std::vector<T, Allocator> > {
1908 // static std::string convert( std::vector<T,Allocator> const& v ) {
1909 // return Detail::rangeToString( v.begin(), v.end() );
1910 // }
1911 //};
1912
1913 template <typename T, typename Allocator>
toString(std::vector<T,Allocator> const & v)1914 std::string toString(std::vector<T, Allocator> const& v)
1915 {
1916 return Detail::rangeToString(v.begin(), v.end());
1917 }
1918
1919 #ifdef CATCH_CONFIG_CPP11_TUPLE
1920
1921 // toString for tuples
1922 namespace TupleDetail {
1923 template <
1924 typename Tuple,
1925 std::size_t N = 0,
1926 bool = (N < std::tuple_size<Tuple>::value)>
1927 struct ElementPrinter
1928 {
printCatch::TupleDetail::ElementPrinter1929 static void print(const Tuple& tuple, std::ostream& os)
1930 {
1931 os << (N ? ", " : " ")
1932 << Catch::toString(std::get<N>(tuple));
1933 ElementPrinter<Tuple, N + 1>::print(tuple, os);
1934 }
1935 };
1936
1937 template <
1938 typename Tuple,
1939 std::size_t N>
1940 struct ElementPrinter<Tuple, N, false>
1941 {
printCatch::TupleDetail::ElementPrinter1942 static void print(const Tuple&, std::ostream&) {}
1943 };
1944 }
1945
1946 template <typename... Types>
1947 struct StringMaker<std::tuple<Types...>>
1948 {
1949
convertCatch::StringMaker1950 static std::string convert(const std::tuple<Types...>& tuple)
1951 {
1952 std::ostringstream os;
1953 os << '{';
1954 TupleDetail::ElementPrinter<std::tuple<Types...>>::print(tuple, os);
1955 os << " }";
1956 return os.str();
1957 }
1958 };
1959 #endif // CATCH_CONFIG_CPP11_TUPLE
1960
1961 namespace Detail {
1962 template <typename T>
makeString(T const & value)1963 std::string makeString(T const& value)
1964 {
1965 return StringMaker<T>::convert(value);
1966 }
1967 } // end namespace Detail
1968
1969 /// \brief converts any type to a string
1970 ///
1971 /// The default template forwards on to ostringstream - except when an
1972 /// ostringstream overload does not exist - in which case it attempts to detect
1973 /// that and writes {?}.
1974 /// Overload (not specialise) this template for custom typs that you don't want
1975 /// to provide an ostream overload for.
1976 template <typename T>
toString(T const & value)1977 std::string toString(T const& value)
1978 {
1979 return StringMaker<T>::convert(value);
1980 }
1981
1982 namespace Detail {
1983 template <typename InputIterator>
rangeToString(InputIterator first,InputIterator last)1984 std::string rangeToString(InputIterator first, InputIterator last)
1985 {
1986 std::ostringstream oss;
1987 oss << "{ ";
1988 if (first != last)
1989 {
1990 oss << Catch::toString(*first);
1991 for (++first; first != last; ++first)
1992 oss << ", " << Catch::toString(*first);
1993 }
1994 oss << " }";
1995 return oss.str();
1996 }
1997 }
1998
1999 } // end namespace Catch
2000
2001 namespace Catch {
2002
2003 // Wraps the LHS of an expression and captures the operator and RHS (if any) -
2004 // wrapping them all in a ResultBuilder object
2005 template <typename T>
2006 class ExpressionLhs
2007 {
2008 ExpressionLhs& operator=(ExpressionLhs const&);
2009 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2010 ExpressionLhs& operator=(ExpressionLhs&&) = delete;
2011 #endif
2012
2013 public:
ExpressionLhs(ResultBuilder & rb,T lhs)2014 ExpressionLhs(ResultBuilder& rb, T lhs) : m_rb(rb), m_lhs(lhs) {}
2015 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2016 ExpressionLhs(ExpressionLhs const&) = default;
2017 ExpressionLhs(ExpressionLhs&&) = default;
2018 #endif
2019
2020 template <typename RhsT>
operator ==(RhsT const & rhs)2021 ResultBuilder& operator==(RhsT const& rhs)
2022 {
2023 return captureExpression<Internal::IsEqualTo>(rhs);
2024 }
2025
2026 template <typename RhsT>
operator !=(RhsT const & rhs)2027 ResultBuilder& operator!=(RhsT const& rhs)
2028 {
2029 return captureExpression<Internal::IsNotEqualTo>(rhs);
2030 }
2031
2032 template <typename RhsT>
operator <(RhsT const & rhs)2033 ResultBuilder& operator<(RhsT const& rhs)
2034 {
2035 return captureExpression<Internal::IsLessThan>(rhs);
2036 }
2037
2038 template <typename RhsT>
operator >(RhsT const & rhs)2039 ResultBuilder& operator>(RhsT const& rhs)
2040 {
2041 return captureExpression<Internal::IsGreaterThan>(rhs);
2042 }
2043
2044 template <typename RhsT>
operator <=(RhsT const & rhs)2045 ResultBuilder& operator<=(RhsT const& rhs)
2046 {
2047 return captureExpression<Internal::IsLessThanOrEqualTo>(rhs);
2048 }
2049
2050 template <typename RhsT>
operator >=(RhsT const & rhs)2051 ResultBuilder& operator>=(RhsT const& rhs)
2052 {
2053 return captureExpression<Internal::IsGreaterThanOrEqualTo>(rhs);
2054 }
2055
operator ==(bool rhs)2056 ResultBuilder& operator==(bool rhs)
2057 {
2058 return captureExpression<Internal::IsEqualTo>(rhs);
2059 }
2060
operator !=(bool rhs)2061 ResultBuilder& operator!=(bool rhs)
2062 {
2063 return captureExpression<Internal::IsNotEqualTo>(rhs);
2064 }
2065
endExpression()2066 void endExpression()
2067 {
2068 bool value = m_lhs ? true : false;
2069 m_rb
2070 .setLhs(Catch::toString(value))
2071 .setResultType(value)
2072 .endExpression();
2073 }
2074
2075 // Only simple binary expressions are allowed on the LHS.
2076 // If more complex compositions are required then place the sub expression in parentheses
2077 template <typename RhsT>
2078 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator+(RhsT const&);
2079 template <typename RhsT>
2080 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator-(RhsT const&);
2081 template <typename RhsT>
2082 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator/(RhsT const&);
2083 template <typename RhsT>
2084 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator*(RhsT const&);
2085 template <typename RhsT>
2086 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator&&(RhsT const&);
2087 template <typename RhsT>
2088 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator||(RhsT const&);
2089
2090 private:
2091 template <Internal::Operator Op, typename RhsT>
captureExpression(RhsT const & rhs)2092 ResultBuilder& captureExpression(RhsT const& rhs)
2093 {
2094 return m_rb
2095 .setResultType(Internal::compare<Op>(m_lhs, rhs))
2096 .setLhs(Catch::toString(m_lhs))
2097 .setRhs(Catch::toString(rhs))
2098 .setOp(Internal::OperatorTraits<Op>::getName());
2099 }
2100
2101 private:
2102 ResultBuilder& m_rb;
2103 T m_lhs;
2104 };
2105
2106 } // end namespace Catch
2107
2108 namespace Catch {
2109
2110 template <typename T>
operator <=(T const & operand)2111 inline ExpressionLhs<T const&> ResultBuilder::operator<=(T const& operand)
2112 {
2113 return ExpressionLhs<T const&>(*this, operand);
2114 }
2115
operator <=(bool value)2116 inline ExpressionLhs<bool> ResultBuilder::operator<=(bool value)
2117 {
2118 return ExpressionLhs<bool>(*this, value);
2119 }
2120
2121 } // namespace Catch
2122
2123 // #included from: catch_message.h
2124 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
2125
2126 #include <string>
2127
2128 namespace Catch {
2129
2130 struct MessageInfo
2131 {
2132 MessageInfo(std::string const& _macroName,
2133 SourceLineInfo const& _lineInfo,
2134 ResultWas::OfType _type);
2135
2136 std::string macroName;
2137 SourceLineInfo lineInfo;
2138 ResultWas::OfType type;
2139 std::string message;
2140 unsigned int sequence;
2141
operator ==Catch::MessageInfo2142 bool operator==(MessageInfo const& other) const
2143 {
2144 return sequence == other.sequence;
2145 }
operator <Catch::MessageInfo2146 bool operator<(MessageInfo const& other) const
2147 {
2148 return sequence < other.sequence;
2149 }
2150
2151 private:
2152 static unsigned int globalCount;
2153 };
2154
2155 struct MessageBuilder
2156 {
MessageBuilderCatch::MessageBuilder2157 MessageBuilder(std::string const& macroName,
2158 SourceLineInfo const& lineInfo,
2159 ResultWas::OfType type)
2160 : m_info(macroName, lineInfo, type)
2161 {
2162 }
2163
2164 template <typename T>
operator <<Catch::MessageBuilder2165 MessageBuilder& operator<<(T const& value)
2166 {
2167 m_stream << value;
2168 return *this;
2169 }
2170
2171 MessageInfo m_info;
2172 std::ostringstream m_stream;
2173 };
2174
2175 class ScopedMessage
2176 {
2177 public:
2178 ScopedMessage(MessageBuilder const& builder);
2179 ScopedMessage(ScopedMessage const& other);
2180 ~ScopedMessage();
2181
2182 MessageInfo m_info;
2183 };
2184
2185 } // end namespace Catch
2186
2187 // #included from: catch_interfaces_capture.h
2188 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
2189
2190 #include <string>
2191
2192 namespace Catch {
2193
2194 class TestCase;
2195 class AssertionResult;
2196 struct AssertionInfo;
2197 struct SectionInfo;
2198 struct SectionEndInfo;
2199 struct MessageInfo;
2200 class ScopedMessageBuilder;
2201 struct Counts;
2202
2203 struct IResultCapture
2204 {
2205
2206 virtual ~IResultCapture();
2207
2208 virtual void assertionEnded(AssertionResult const& result) = 0;
2209 virtual bool sectionStarted(SectionInfo const& sectionInfo,
2210 Counts& assertions) = 0;
2211 virtual void sectionEnded(SectionEndInfo const& endInfo) = 0;
2212 virtual void sectionEndedEarly(SectionEndInfo const& endInfo) = 0;
2213 virtual void pushScopedMessage(MessageInfo const& message) = 0;
2214 virtual void popScopedMessage(MessageInfo const& message) = 0;
2215
2216 virtual std::string getCurrentTestName() const = 0;
2217 virtual const AssertionResult* getLastResult() const = 0;
2218
2219 virtual void handleFatalErrorCondition(std::string const& message) = 0;
2220 };
2221
2222 IResultCapture& getResultCapture();
2223 }
2224
2225 // #included from: catch_debugger.h
2226 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
2227
2228 // #included from: catch_platform.h
2229 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
2230
2231 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
2232 #define CATCH_PLATFORM_MAC
2233 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
2234 #define CATCH_PLATFORM_IPHONE
2235 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
2236 #define CATCH_PLATFORM_WINDOWS
2237 #endif
2238
2239 #include <string>
2240
2241 namespace Catch {
2242
2243 bool isDebuggerActive();
2244 void writeToDebugConsole(std::string const& text);
2245 }
2246
2247 #ifdef CATCH_PLATFORM_MAC
2248
2249 // The following code snippet based on:
2250 // http://cocoawithlove.com/2008/03/break-into-debugger.html
2251 #ifdef DEBUG
2252 #if defined(__ppc64__) || defined(__ppc__)
2253 #define CATCH_BREAK_INTO_DEBUGGER() \
2254 if (Catch::isDebuggerActive()) \
2255 { \
2256 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
2257 : \
2258 : \
2259 : "memory", "r0", "r3", "r4"); \
2260 }
2261 #else
2262 #define CATCH_BREAK_INTO_DEBUGGER() \
2263 if (Catch::isDebuggerActive()) \
2264 { \
2265 __asm__("int $3\n" \
2266 : \
2267 :); \
2268 }
2269 #endif
2270 #endif
2271
2272 #elif defined(_MSC_VER)
2273 #define CATCH_BREAK_INTO_DEBUGGER() \
2274 if (Catch::isDebuggerActive()) \
2275 { \
2276 __debugbreak(); \
2277 }
2278 #elif defined(__MINGW32__)
2279 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
2280 #define CATCH_BREAK_INTO_DEBUGGER() \
2281 if (Catch::isDebuggerActive()) \
2282 { \
2283 DebugBreak(); \
2284 }
2285 #endif
2286
2287 #ifndef CATCH_BREAK_INTO_DEBUGGER
2288 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
2289 #endif
2290
2291 // #included from: catch_interfaces_runner.h
2292 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2293
2294 namespace Catch {
2295 class TestCase;
2296
2297 struct IRunner
2298 {
2299 virtual ~IRunner();
2300 virtual bool aborting() const = 0;
2301 };
2302 }
2303
2304 ///////////////////////////////////////////////////////////////////////////////
2305 // In the event of a failure works out if the debugger needs to be invoked
2306 // and/or an exception thrown and takes appropriate action.
2307 // This needs to be done as a macro so the debugger will stop in the user
2308 // source code rather than in Catch library code
2309 #define INTERNAL_CATCH_REACT(resultBuilder) \
2310 if (resultBuilder.shouldDebugBreak()) CATCH_BREAK_INTO_DEBUGGER(); \
2311 resultBuilder.react();
2312
2313 ///////////////////////////////////////////////////////////////////////////////
2314 #define INTERNAL_CATCH_TEST(expr, resultDisposition, macroName) \
2315 do \
2316 { \
2317 Catch::ResultBuilder __catchResult(macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition); \
2318 try \
2319 { \
2320 (__catchResult <= expr).endExpression(); \
2321 } \
2322 catch (...) \
2323 { \
2324 __catchResult.useActiveException(Catch::ResultDisposition::Normal); \
2325 } \
2326 INTERNAL_CATCH_REACT(__catchResult) \
2327 } while (Catch::isTrue(false && (expr))) // expr here is never evaluated at runtime but it forces the compiler to give it a look
2328
2329 ///////////////////////////////////////////////////////////////////////////////
2330 #define INTERNAL_CATCH_IF(expr, resultDisposition, macroName) \
2331 INTERNAL_CATCH_TEST(expr, resultDisposition, macroName); \
2332 if (Catch::getResultCapture().getLastResult()->succeeded())
2333
2334 ///////////////////////////////////////////////////////////////////////////////
2335 #define INTERNAL_CATCH_ELSE(expr, resultDisposition, macroName) \
2336 INTERNAL_CATCH_TEST(expr, resultDisposition, macroName); \
2337 if (!Catch::getResultCapture().getLastResult()->succeeded())
2338
2339 ///////////////////////////////////////////////////////////////////////////////
2340 #define INTERNAL_CATCH_NO_THROW(expr, resultDisposition, macroName) \
2341 do \
2342 { \
2343 Catch::ResultBuilder __catchResult(macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition); \
2344 try \
2345 { \
2346 expr; \
2347 __catchResult.captureResult(Catch::ResultWas::Ok); \
2348 } \
2349 catch (...) \
2350 { \
2351 __catchResult.useActiveException(resultDisposition); \
2352 } \
2353 INTERNAL_CATCH_REACT(__catchResult) \
2354 } while (Catch::alwaysFalse())
2355
2356 ///////////////////////////////////////////////////////////////////////////////
2357 #define INTERNAL_CATCH_THROWS(expr, resultDisposition, matcher, macroName) \
2358 do \
2359 { \
2360 Catch::ResultBuilder __catchResult(macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher); \
2361 if (__catchResult.allowThrows()) \
2362 try \
2363 { \
2364 expr; \
2365 __catchResult.captureResult(Catch::ResultWas::DidntThrowException); \
2366 } \
2367 catch (...) \
2368 { \
2369 __catchResult.captureExpectedException(matcher); \
2370 } \
2371 else \
2372 __catchResult.captureResult(Catch::ResultWas::Ok); \
2373 INTERNAL_CATCH_REACT(__catchResult) \
2374 } while (Catch::alwaysFalse())
2375
2376 ///////////////////////////////////////////////////////////////////////////////
2377 #define INTERNAL_CATCH_THROWS_AS(expr, exceptionType, resultDisposition, macroName) \
2378 do \
2379 { \
2380 Catch::ResultBuilder __catchResult(macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition); \
2381 if (__catchResult.allowThrows()) \
2382 try \
2383 { \
2384 expr; \
2385 __catchResult.captureResult(Catch::ResultWas::DidntThrowException); \
2386 } \
2387 catch (exceptionType) \
2388 { \
2389 __catchResult.captureResult(Catch::ResultWas::Ok); \
2390 } \
2391 catch (...) \
2392 { \
2393 __catchResult.useActiveException(resultDisposition); \
2394 } \
2395 else \
2396 __catchResult.captureResult(Catch::ResultWas::Ok); \
2397 INTERNAL_CATCH_REACT(__catchResult) \
2398 } while (Catch::alwaysFalse())
2399
2400 ///////////////////////////////////////////////////////////////////////////////
2401 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2402 #define INTERNAL_CATCH_MSG(messageType, resultDisposition, macroName, ...) \
2403 do \
2404 { \
2405 Catch::ResultBuilder __catchResult(macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition); \
2406 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2407 __catchResult.captureResult(messageType); \
2408 INTERNAL_CATCH_REACT(__catchResult) \
2409 } while (Catch::alwaysFalse())
2410 #else
2411 #define INTERNAL_CATCH_MSG(messageType, resultDisposition, macroName, log) \
2412 do \
2413 { \
2414 Catch::ResultBuilder __catchResult(macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition); \
2415 __catchResult << log + ::Catch::StreamEndStop(); \
2416 __catchResult.captureResult(messageType); \
2417 INTERNAL_CATCH_REACT(__catchResult) \
2418 } while (Catch::alwaysFalse())
2419 #endif
2420
2421 ///////////////////////////////////////////////////////////////////////////////
2422 #define INTERNAL_CATCH_INFO(log, macroName) \
2423 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME(scopedMessage) = Catch::MessageBuilder(macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info) << log;
2424
2425 ///////////////////////////////////////////////////////////////////////////////
2426 #define INTERNAL_CHECK_THAT(arg, matcher, resultDisposition, macroName) \
2427 do \
2428 { \
2429 Catch::ResultBuilder __catchResult(macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition); \
2430 try \
2431 { \
2432 std::string matcherAsString = (matcher).toString(); \
2433 __catchResult \
2434 .setLhs(Catch::toString(arg)) \
2435 .setRhs(matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString) \
2436 .setOp("matches") \
2437 .setResultType((matcher).match(arg)); \
2438 __catchResult.captureExpression(); \
2439 } \
2440 catch (...) \
2441 { \
2442 __catchResult.useActiveException(resultDisposition | Catch::ResultDisposition::ContinueOnFailure); \
2443 } \
2444 INTERNAL_CATCH_REACT(__catchResult) \
2445 } while (Catch::alwaysFalse())
2446
2447 // #included from: internal/catch_section.h
2448 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2449
2450 // #included from: catch_section_info.h
2451 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2452
2453 // #included from: catch_totals.hpp
2454 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2455
2456 #include <cstddef>
2457
2458 namespace Catch {
2459
2460 struct Counts
2461 {
CountsCatch::Counts2462 Counts() : passed(0), failed(0), failedButOk(0) {}
2463
operator -Catch::Counts2464 Counts operator-(Counts const& other) const
2465 {
2466 Counts diff;
2467 diff.passed = passed - other.passed;
2468 diff.failed = failed - other.failed;
2469 diff.failedButOk = failedButOk - other.failedButOk;
2470 return diff;
2471 }
operator +=Catch::Counts2472 Counts& operator+=(Counts const& other)
2473 {
2474 passed += other.passed;
2475 failed += other.failed;
2476 failedButOk += other.failedButOk;
2477 return *this;
2478 }
2479
totalCatch::Counts2480 std::size_t total() const
2481 {
2482 return passed + failed + failedButOk;
2483 }
allPassedCatch::Counts2484 bool allPassed() const
2485 {
2486 return failed == 0 && failedButOk == 0;
2487 }
allOkCatch::Counts2488 bool allOk() const
2489 {
2490 return failed == 0;
2491 }
2492
2493 std::size_t passed;
2494 std::size_t failed;
2495 std::size_t failedButOk;
2496 };
2497
2498 struct Totals
2499 {
2500
operator -Catch::Totals2501 Totals operator-(Totals const& other) const
2502 {
2503 Totals diff;
2504 diff.assertions = assertions - other.assertions;
2505 diff.testCases = testCases - other.testCases;
2506 return diff;
2507 }
2508
deltaCatch::Totals2509 Totals delta(Totals const& prevTotals) const
2510 {
2511 Totals diff = *this - prevTotals;
2512 if (diff.assertions.failed > 0)
2513 ++diff.testCases.failed;
2514 else if (diff.assertions.failedButOk > 0)
2515 ++diff.testCases.failedButOk;
2516 else
2517 ++diff.testCases.passed;
2518 return diff;
2519 }
2520
operator +=Catch::Totals2521 Totals& operator+=(Totals const& other)
2522 {
2523 assertions += other.assertions;
2524 testCases += other.testCases;
2525 return *this;
2526 }
2527
2528 Counts assertions;
2529 Counts testCases;
2530 };
2531 }
2532
2533 namespace Catch {
2534
2535 struct SectionInfo
2536 {
2537 SectionInfo(SourceLineInfo const& _lineInfo,
2538 std::string const& _name,
2539 std::string const& _description = std::string());
2540
2541 std::string name;
2542 std::string description;
2543 SourceLineInfo lineInfo;
2544 };
2545
2546 struct SectionEndInfo
2547 {
SectionEndInfoCatch::SectionEndInfo2548 SectionEndInfo(SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds)
2549 : sectionInfo(_sectionInfo), prevAssertions(_prevAssertions), durationInSeconds(_durationInSeconds)
2550 {
2551 }
2552
2553 SectionInfo sectionInfo;
2554 Counts prevAssertions;
2555 double durationInSeconds;
2556 };
2557
2558 } // end namespace Catch
2559
2560 // #included from: catch_timer.h
2561 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2562
2563 #ifdef CATCH_PLATFORM_WINDOWS
2564 typedef unsigned long long uint64_t;
2565 #else
2566 #include <stdint.h>
2567 #endif
2568
2569 namespace Catch {
2570
2571 class Timer
2572 {
2573 public:
Timer()2574 Timer() : m_ticks(0) {}
2575 void start();
2576 unsigned int getElapsedMicroseconds() const;
2577 unsigned int getElapsedMilliseconds() const;
2578 double getElapsedSeconds() const;
2579
2580 private:
2581 uint64_t m_ticks;
2582 };
2583
2584 } // namespace Catch
2585
2586 #include <string>
2587
2588 namespace Catch {
2589
2590 class Section : NonCopyable
2591 {
2592 public:
2593 Section(SectionInfo const& info);
2594 ~Section();
2595
2596 // This indicates whether the section should be executed or not
2597 operator bool() const;
2598
2599 private:
2600 SectionInfo m_info;
2601
2602 std::string m_name;
2603 Counts m_assertions;
2604 bool m_sectionIncluded;
2605 Timer m_timer;
2606 };
2607
2608 } // end namespace Catch
2609
2610 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2611 #define INTERNAL_CATCH_SECTION(...) \
2612 if (Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME(catch_internal_Section) = Catch::SectionInfo(CATCH_INTERNAL_LINEINFO, __VA_ARGS__))
2613 #else
2614 #define INTERNAL_CATCH_SECTION(name, desc) \
2615 if (Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME(catch_internal_Section) = Catch::SectionInfo(CATCH_INTERNAL_LINEINFO, name, desc))
2616 #endif
2617
2618 // #included from: internal/catch_generators.hpp
2619 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2620
2621 #include <iterator>
2622 #include <stdlib.h>
2623 #include <string>
2624 #include <vector>
2625
2626 namespace Catch {
2627
2628 template <typename T>
2629 struct IGenerator
2630 {
~IGeneratorCatch::IGenerator2631 virtual ~IGenerator() {}
2632 virtual T getValue(std::size_t index) const = 0;
2633 virtual std::size_t size() const = 0;
2634 };
2635
2636 template <typename T>
2637 class BetweenGenerator : public IGenerator<T>
2638 {
2639 public:
BetweenGenerator(T from,T to)2640 BetweenGenerator(T from, T to) : m_from(from), m_to(to) {}
2641
getValue(std::size_t index) const2642 virtual T getValue(std::size_t index) const
2643 {
2644 return m_from + static_cast<int>(index);
2645 }
2646
size() const2647 virtual std::size_t size() const
2648 {
2649 return static_cast<std::size_t>(1 + m_to - m_from);
2650 }
2651
2652 private:
2653 T m_from;
2654 T m_to;
2655 };
2656
2657 template <typename T>
2658 class ValuesGenerator : public IGenerator<T>
2659 {
2660 public:
ValuesGenerator()2661 ValuesGenerator() {}
2662
add(T value)2663 void add(T value)
2664 {
2665 m_values.push_back(value);
2666 }
2667
getValue(std::size_t index) const2668 virtual T getValue(std::size_t index) const
2669 {
2670 return m_values[index];
2671 }
2672
size() const2673 virtual std::size_t size() const
2674 {
2675 return m_values.size();
2676 }
2677
2678 private:
2679 std::vector<T> m_values;
2680 };
2681
2682 template <typename T>
2683 class CompositeGenerator
2684 {
2685 public:
CompositeGenerator()2686 CompositeGenerator() : m_totalSize(0) {}
2687
2688 // *** Move semantics, similar to auto_ptr ***
CompositeGenerator(CompositeGenerator & other)2689 CompositeGenerator(CompositeGenerator& other)
2690 : m_fileInfo(other.m_fileInfo),
2691 m_totalSize(0)
2692 {
2693 move(other);
2694 }
2695
setFileInfo(const char * fileInfo)2696 CompositeGenerator& setFileInfo(const char* fileInfo)
2697 {
2698 m_fileInfo = fileInfo;
2699 return *this;
2700 }
2701
~CompositeGenerator()2702 ~CompositeGenerator()
2703 {
2704 deleteAll(m_composed);
2705 }
2706
operator T() const2707 operator T() const
2708 {
2709 size_t overallIndex = getCurrentContext().getGeneratorIndex(m_fileInfo, m_totalSize);
2710
2711 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2712 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2713 for (size_t index = 0; it != itEnd; ++it)
2714 {
2715 const IGenerator<T>* generator = *it;
2716 if (overallIndex >= index && overallIndex < index + generator->size())
2717 {
2718 return generator->getValue(overallIndex - index);
2719 }
2720 index += generator->size();
2721 }
2722 CATCH_INTERNAL_ERROR("Indexed past end of generated range");
2723 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
2724 }
2725
add(const IGenerator<T> * generator)2726 void add(const IGenerator<T>* generator)
2727 {
2728 m_totalSize += generator->size();
2729 m_composed.push_back(generator);
2730 }
2731
then(CompositeGenerator & other)2732 CompositeGenerator& then(CompositeGenerator& other)
2733 {
2734 move(other);
2735 return *this;
2736 }
2737
then(T value)2738 CompositeGenerator& then(T value)
2739 {
2740 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2741 valuesGen->add(value);
2742 add(valuesGen);
2743 return *this;
2744 }
2745
2746 private:
move(CompositeGenerator & other)2747 void move(CompositeGenerator& other)
2748 {
2749 std::copy(other.m_composed.begin(), other.m_composed.end(), std::back_inserter(m_composed));
2750 m_totalSize += other.m_totalSize;
2751 other.m_composed.clear();
2752 }
2753
2754 std::vector<const IGenerator<T>*> m_composed;
2755 std::string m_fileInfo;
2756 size_t m_totalSize;
2757 };
2758
2759 namespace Generators {
2760 template <typename T>
between(T from,T to)2761 CompositeGenerator<T> between(T from, T to)
2762 {
2763 CompositeGenerator<T> generators;
2764 generators.add(new BetweenGenerator<T>(from, to));
2765 return generators;
2766 }
2767
2768 template <typename T>
values(T val1,T val2)2769 CompositeGenerator<T> values(T val1, T val2)
2770 {
2771 CompositeGenerator<T> generators;
2772 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2773 valuesGen->add(val1);
2774 valuesGen->add(val2);
2775 generators.add(valuesGen);
2776 return generators;
2777 }
2778
2779 template <typename T>
values(T val1,T val2,T val3)2780 CompositeGenerator<T> values(T val1, T val2, T val3)
2781 {
2782 CompositeGenerator<T> generators;
2783 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2784 valuesGen->add(val1);
2785 valuesGen->add(val2);
2786 valuesGen->add(val3);
2787 generators.add(valuesGen);
2788 return generators;
2789 }
2790
2791 template <typename T>
values(T val1,T val2,T val3,T val4)2792 CompositeGenerator<T> values(T val1, T val2, T val3, T val4)
2793 {
2794 CompositeGenerator<T> generators;
2795 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2796 valuesGen->add(val1);
2797 valuesGen->add(val2);
2798 valuesGen->add(val3);
2799 valuesGen->add(val4);
2800 generators.add(valuesGen);
2801 return generators;
2802 }
2803
2804 } // end namespace Generators
2805
2806 using namespace Generators;
2807
2808 } // end namespace Catch
2809
2810 #define INTERNAL_CATCH_LINESTR2(line) #line
2811 #define INTERNAL_CATCH_LINESTR(line) INTERNAL_CATCH_LINESTR2(line)
2812
2813 #define INTERNAL_CATCH_GENERATE(expr) expr.setFileInfo(__FILE__ "(" INTERNAL_CATCH_LINESTR(__LINE__) ")")
2814
2815 // #included from: internal/catch_interfaces_exception.h
2816 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2817
2818 #include <string>
2819 #include <vector>
2820
2821 // #included from: catch_interfaces_registry_hub.h
2822 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2823
2824 #include <string>
2825
2826 namespace Catch {
2827
2828 class TestCase;
2829 struct ITestCaseRegistry;
2830 struct IExceptionTranslatorRegistry;
2831 struct IExceptionTranslator;
2832 struct IReporterRegistry;
2833 struct IReporterFactory;
2834
2835 struct IRegistryHub
2836 {
2837 virtual ~IRegistryHub();
2838
2839 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2840 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2841 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2842 };
2843
2844 struct IMutableRegistryHub
2845 {
2846 virtual ~IMutableRegistryHub();
2847 virtual void registerReporter(std::string const& name, Ptr<IReporterFactory> const& factory) = 0;
2848 virtual void registerListener(Ptr<IReporterFactory> const& factory) = 0;
2849 virtual void registerTest(TestCase const& testInfo) = 0;
2850 virtual void registerTranslator(const IExceptionTranslator* translator) = 0;
2851 };
2852
2853 IRegistryHub& getRegistryHub();
2854 IMutableRegistryHub& getMutableRegistryHub();
2855 void cleanUp();
2856 std::string translateActiveException();
2857 }
2858
2859 namespace Catch {
2860
2861 typedef std::string (*exceptionTranslateFunction)();
2862
2863 struct IExceptionTranslator;
2864 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2865
2866 struct IExceptionTranslator
2867 {
2868 virtual ~IExceptionTranslator();
2869 virtual std::string translate(ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd) const = 0;
2870 };
2871
2872 struct IExceptionTranslatorRegistry
2873 {
2874 virtual ~IExceptionTranslatorRegistry();
2875
2876 virtual std::string translateActiveException() const = 0;
2877 };
2878
2879 class ExceptionTranslatorRegistrar
2880 {
2881 template <typename T>
2882 class ExceptionTranslator : public IExceptionTranslator
2883 {
2884 public:
ExceptionTranslator(std::string (* translateFunction)(T &))2885 ExceptionTranslator(std::string (*translateFunction)(T&))
2886 : m_translateFunction(translateFunction)
2887 {
2888 }
2889
translate(ExceptionTranslators::const_iterator it,ExceptionTranslators::const_iterator itEnd) const2890 virtual std::string translate(ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd) const CATCH_OVERRIDE
2891 {
2892 try
2893 {
2894 if (it == itEnd)
2895 throw;
2896 else
2897 return (*it)->translate(it + 1, itEnd);
2898 }
2899 catch (T& ex)
2900 {
2901 return m_translateFunction(ex);
2902 }
2903 }
2904
2905 protected:
2906 std::string (*m_translateFunction)(T&);
2907 };
2908
2909 public:
2910 template <typename T>
ExceptionTranslatorRegistrar(std::string (* translateFunction)(T &))2911 ExceptionTranslatorRegistrar(std::string (*translateFunction)(T&))
2912 {
2913 getMutableRegistryHub().registerTranslator(new ExceptionTranslator<T>(translateFunction));
2914 }
2915 };
2916 }
2917
2918 ///////////////////////////////////////////////////////////////////////////////
2919 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION(signature) \
2920 static std::string INTERNAL_CATCH_UNIQUE_NAME(catch_internal_ExceptionTranslator)(signature); \
2921 namespace { \
2922 Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME(catch_internal_ExceptionRegistrar)(&INTERNAL_CATCH_UNIQUE_NAME(catch_internal_ExceptionTranslator)); \
2923 } \
2924 static std::string INTERNAL_CATCH_UNIQUE_NAME(catch_internal_ExceptionTranslator)(signature)
2925
2926 // #included from: internal/catch_approx.hpp
2927 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2928
2929 #include <cmath>
2930 #include <limits>
2931
2932 namespace Catch {
2933 namespace Detail {
2934
2935 class Approx
2936 {
2937 public:
Approx(double value)2938 explicit Approx(double value)
2939 : m_epsilon(std::numeric_limits<float>::epsilon() * 100),
2940 m_scale(1.0),
2941 m_value(value)
2942 {
2943 }
2944
Approx(Approx const & other)2945 Approx(Approx const& other)
2946 : m_epsilon(other.m_epsilon),
2947 m_scale(other.m_scale),
2948 m_value(other.m_value)
2949 {
2950 }
2951
custom()2952 static Approx custom()
2953 {
2954 return Approx(0);
2955 }
2956
operator ()(double value)2957 Approx operator()(double value)
2958 {
2959 Approx approx(value);
2960 approx.epsilon(m_epsilon);
2961 approx.scale(m_scale);
2962 return approx;
2963 }
2964
operator ==(double lhs,Approx const & rhs)2965 friend bool operator==(double lhs, Approx const& rhs)
2966 {
2967 // Thanks to Richard Harris for his help refining this formula
2968 return fabs(lhs - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(fabs(lhs), fabs(rhs.m_value)));
2969 }
2970
operator ==(Approx const & lhs,double rhs)2971 friend bool operator==(Approx const& lhs, double rhs)
2972 {
2973 return operator==(rhs, lhs);
2974 }
2975
operator !=(double lhs,Approx const & rhs)2976 friend bool operator!=(double lhs, Approx const& rhs)
2977 {
2978 return !operator==(lhs, rhs);
2979 }
2980
operator !=(Approx const & lhs,double rhs)2981 friend bool operator!=(Approx const& lhs, double rhs)
2982 {
2983 return !operator==(rhs, lhs);
2984 }
2985
epsilon(double newEpsilon)2986 Approx& epsilon(double newEpsilon)
2987 {
2988 m_epsilon = newEpsilon;
2989 return *this;
2990 }
2991
scale(double newScale)2992 Approx& scale(double newScale)
2993 {
2994 m_scale = newScale;
2995 return *this;
2996 }
2997
toString() const2998 std::string toString() const
2999 {
3000 std::ostringstream oss;
3001 oss << "Approx( " << Catch::toString(m_value) << " )";
3002 return oss.str();
3003 }
3004
3005 private:
3006 double m_epsilon;
3007 double m_scale;
3008 double m_value;
3009 };
3010 }
3011
3012 template <>
toString(Detail::Approx const & value)3013 inline std::string toString<Detail::Approx>(Detail::Approx const& value)
3014 {
3015 return value.toString();
3016 }
3017
3018 } // end namespace Catch
3019
3020 // #included from: internal/catch_interfaces_tag_alias_registry.h
3021 #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
3022
3023 // #included from: catch_tag_alias.h
3024 #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
3025
3026 #include <string>
3027
3028 namespace Catch {
3029
3030 struct TagAlias
3031 {
TagAliasCatch::TagAlias3032 TagAlias(std::string _tag, SourceLineInfo _lineInfo) : tag(_tag), lineInfo(_lineInfo) {}
3033
3034 std::string tag;
3035 SourceLineInfo lineInfo;
3036 };
3037
3038 struct RegistrarForTagAliases
3039 {
3040 RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo);
3041 };
3042
3043 } // end namespace Catch
3044
3045 #define CATCH_REGISTER_TAG_ALIAS(alias, spec) \
3046 namespace { \
3047 Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME(AutoRegisterTagAlias)(alias, spec, CATCH_INTERNAL_LINEINFO); \
3048 }
3049 // #included from: catch_option.hpp
3050 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
3051
3052 namespace Catch {
3053
3054 // An optional type
3055 template <typename T>
3056 class Option
3057 {
3058 public:
Option()3059 Option() : nullableValue(CATCH_NULL) {}
Option(T const & _value)3060 Option(T const& _value)
3061 : nullableValue(new (storage) T(_value))
3062 {
3063 }
Option(Option const & _other)3064 Option(Option const& _other)
3065 : nullableValue(_other ? new (storage) T(*_other) : CATCH_NULL)
3066 {
3067 }
3068
~Option()3069 ~Option()
3070 {
3071 reset();
3072 }
3073
operator =(Option const & _other)3074 Option& operator=(Option const& _other)
3075 {
3076 if (&_other != this)
3077 {
3078 reset();
3079 if (_other)
3080 nullableValue = new (storage) T(*_other);
3081 }
3082 return *this;
3083 }
operator =(T const & _value)3084 Option& operator=(T const& _value)
3085 {
3086 reset();
3087 nullableValue = new (storage) T(_value);
3088 return *this;
3089 }
3090
reset()3091 void reset()
3092 {
3093 if (nullableValue)
3094 nullableValue->~T();
3095 nullableValue = CATCH_NULL;
3096 }
3097
operator *()3098 T& operator*() { return *nullableValue; }
operator *() const3099 T const& operator*() const { return *nullableValue; }
operator ->()3100 T* operator->() { return nullableValue; }
operator ->() const3101 const T* operator->() const { return nullableValue; }
3102
valueOr(T const & defaultValue) const3103 T valueOr(T const& defaultValue) const
3104 {
3105 return nullableValue ? *nullableValue : defaultValue;
3106 }
3107
some() const3108 bool some() const { return nullableValue != CATCH_NULL; }
none() const3109 bool none() const { return nullableValue == CATCH_NULL; }
3110
operator !() const3111 bool operator!() const { return nullableValue == CATCH_NULL; }
operator SafeBool::type() const3112 operator SafeBool::type() const
3113 {
3114 return SafeBool::makeSafe(some());
3115 }
3116
3117 private:
3118 T* nullableValue;
3119 char storage[sizeof(T)];
3120 };
3121
3122 } // end namespace Catch
3123
3124 namespace Catch {
3125
3126 struct ITagAliasRegistry
3127 {
3128 virtual ~ITagAliasRegistry();
3129 virtual Option<TagAlias> find(std::string const& alias) const = 0;
3130 virtual std::string expandAliases(std::string const& unexpandedTestSpec) const = 0;
3131
3132 static ITagAliasRegistry const& get();
3133 };
3134
3135 } // end namespace Catch
3136
3137 // These files are included here so the single_include script doesn't put them
3138 // in the conditionally compiled sections
3139 // #included from: internal/catch_test_case_info.h
3140 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
3141
3142 #include <set>
3143 #include <string>
3144
3145 #ifdef __clang__
3146 #pragma clang diagnostic push
3147 #pragma clang diagnostic ignored "-Wpadded"
3148 #endif
3149
3150 namespace Catch {
3151
3152 struct ITestCase;
3153
3154 struct TestCaseInfo
3155 {
3156 enum SpecialProperties
3157 {
3158 None = 0,
3159 IsHidden = 1 << 1,
3160 ShouldFail = 1 << 2,
3161 MayFail = 1 << 3,
3162 Throws = 1 << 4
3163 };
3164
3165 TestCaseInfo(std::string const& _name,
3166 std::string const& _className,
3167 std::string const& _description,
3168 std::set<std::string> const& _tags,
3169 SourceLineInfo const& _lineInfo);
3170
3171 TestCaseInfo(TestCaseInfo const& other);
3172
3173 friend void setTags(TestCaseInfo& testCaseInfo, std::set<std::string> const& tags);
3174
3175 bool isHidden() const;
3176 bool throws() const;
3177 bool okToFail() const;
3178 bool expectedToFail() const;
3179
3180 std::string name;
3181 std::string className;
3182 std::string description;
3183 std::set<std::string> tags;
3184 std::set<std::string> lcaseTags;
3185 std::string tagsAsString;
3186 SourceLineInfo lineInfo;
3187 SpecialProperties properties;
3188 };
3189
3190 class TestCase : public TestCaseInfo
3191 {
3192 public:
3193 TestCase(ITestCase* testCase, TestCaseInfo const& info);
3194 TestCase(TestCase const& other);
3195
3196 TestCase withName(std::string const& _newName) const;
3197
3198 void invoke() const;
3199
3200 TestCaseInfo const& getTestCaseInfo() const;
3201
3202 void swap(TestCase& other);
3203 bool operator==(TestCase const& other) const;
3204 bool operator<(TestCase const& other) const;
3205 TestCase& operator=(TestCase const& other);
3206
3207 private:
3208 Ptr<ITestCase> test;
3209 };
3210
3211 TestCase makeTestCase(ITestCase* testCase,
3212 std::string const& className,
3213 std::string const& name,
3214 std::string const& description,
3215 SourceLineInfo const& lineInfo);
3216 }
3217
3218 #ifdef __clang__
3219 #pragma clang diagnostic pop
3220 #endif
3221
3222 #ifdef __OBJC__
3223 // #included from: internal/catch_objc.hpp
3224 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
3225
3226 #import <objc/runtime.h>
3227
3228 #include <string>
3229
3230 // NB. Any general catch headers included here must be included
3231 // in catch.hpp first to make sure they are included by the single
3232 // header for non obj-usage
3233
3234 ///////////////////////////////////////////////////////////////////////////////
3235 // This protocol is really only here for (self) documenting purposes, since
3236 // all its methods are optional.
3237 @protocol OcFixture
3238
3239 @optional
3240
3241 - (void)setUp;
3242 - (void)tearDown;
3243
3244 @end
3245
3246 namespace Catch {
3247
3248 class OcMethod : public SharedImpl<ITestCase>
3249 {
3250
3251 public:
OcMethod(Class cls,SEL sel)3252 OcMethod(Class cls, SEL sel) : m_cls(cls), m_sel(sel) {}
3253
invoke() const3254 virtual void invoke() const
3255 {
3256 id obj = [[m_cls alloc] init];
3257
3258 performOptionalSelector(obj, @selector(setUp));
3259 performOptionalSelector(obj, m_sel);
3260 performOptionalSelector(obj, @selector(tearDown));
3261
3262 arcSafeRelease(obj);
3263 }
3264
3265 private:
~OcMethod()3266 virtual ~OcMethod() {}
3267
3268 Class m_cls;
3269 SEL m_sel;
3270 };
3271
3272 namespace Detail {
3273
getAnnotation(Class cls,std::string const & annotationName,std::string const & testCaseName)3274 inline std::string getAnnotation(Class cls,
3275 std::string const& annotationName,
3276 std::string const& testCaseName)
3277 {
3278 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
3279 SEL sel = NSSelectorFromString(selStr);
3280 arcSafeRelease(selStr);
3281 id value = performOptionalSelector(cls, sel);
3282 if (value)
3283 return [(NSString*)value UTF8String];
3284 return "";
3285 }
3286 }
3287
registerTestMethods()3288 inline size_t registerTestMethods()
3289 {
3290 size_t noTestMethods = 0;
3291 int noClasses = objc_getClassList(CATCH_NULL, 0);
3292
3293 Class* classes = (CATCH_UNSAFE_UNRETAINED Class*)malloc(sizeof(Class) * noClasses);
3294 objc_getClassList(classes, noClasses);
3295
3296 for (int c = 0; c < noClasses; c++)
3297 {
3298 Class cls = classes[c];
3299 {
3300 u_int count;
3301 Method* methods = class_copyMethodList(cls, &count);
3302 for (u_int m = 0; m < count; m++)
3303 {
3304 SEL selector = method_getName(methods[m]);
3305 std::string methodName = sel_getName(selector);
3306 if (startsWith(methodName, "Catch_TestCase_"))
3307 {
3308 std::string testCaseName = methodName.substr(15);
3309 std::string name = Detail::getAnnotation(cls, "Name", testCaseName);
3310 std::string desc = Detail::getAnnotation(cls, "Description", testCaseName);
3311 const char* className = class_getName(cls);
3312
3313 getMutableRegistryHub().registerTest(makeTestCase(new OcMethod(cls, selector), className, name.c_str(), desc.c_str(), SourceLineInfo()));
3314 noTestMethods++;
3315 }
3316 }
3317 free(methods);
3318 }
3319 }
3320 return noTestMethods;
3321 }
3322
3323 namespace Matchers {
3324 namespace Impl {
3325 namespace NSStringMatchers {
3326
3327 template <typename MatcherT>
3328 struct StringHolder : MatcherImpl<MatcherT, NSString*>
3329 {
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder3330 StringHolder(NSString* substr) : m_substr([substr copy]) {}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder3331 StringHolder(StringHolder const& other) : m_substr([other.m_substr copy]) {}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder3332 StringHolder()
3333 {
3334 arcSafeRelease(m_substr);
3335 }
3336
3337 NSString* m_substr;
3338 };
3339
3340 struct Equals : StringHolder<Equals>
3341 {
EqualsCatch::Matchers::Impl::NSStringMatchers::Equals3342 Equals(NSString* substr) : StringHolder(substr) {}
3343
matchCatch::Matchers::Impl::NSStringMatchers::Equals3344 virtual bool match(ExpressionType const& str) const
3345 {
3346 return (str != nil || m_substr == nil) &&
3347 [str isEqualToString:m_substr];
3348 }
3349
toStringCatch::Matchers::Impl::NSStringMatchers::Equals3350 virtual std::string toString() const
3351 {
3352 return "equals string: " + Catch::toString(m_substr);
3353 }
3354 };
3355
3356 struct Contains : StringHolder<Contains>
3357 {
ContainsCatch::Matchers::Impl::NSStringMatchers::Contains3358 Contains(NSString* substr) : StringHolder(substr) {}
3359
matchCatch::Matchers::Impl::NSStringMatchers::Contains3360 virtual bool match(ExpressionType const& str) const
3361 {
3362 return (str != nil || m_substr == nil) &&
3363 [str rangeOfString:m_substr].location != NSNotFound;
3364 }
3365
toStringCatch::Matchers::Impl::NSStringMatchers::Contains3366 virtual std::string toString() const
3367 {
3368 return "contains string: " + Catch::toString(m_substr);
3369 }
3370 };
3371
3372 struct StartsWith : StringHolder<StartsWith>
3373 {
StartsWithCatch::Matchers::Impl::NSStringMatchers::StartsWith3374 StartsWith(NSString* substr) : StringHolder(substr) {}
3375
matchCatch::Matchers::Impl::NSStringMatchers::StartsWith3376 virtual bool match(ExpressionType const& str) const
3377 {
3378 return (str != nil || m_substr == nil) &&
3379 [str rangeOfString:m_substr].location == 0;
3380 }
3381
toStringCatch::Matchers::Impl::NSStringMatchers::StartsWith3382 virtual std::string toString() const
3383 {
3384 return "starts with: " + Catch::toString(m_substr);
3385 }
3386 };
3387 struct EndsWith : StringHolder<EndsWith>
3388 {
EndsWithCatch::Matchers::Impl::NSStringMatchers::EndsWith3389 EndsWith(NSString* substr) : StringHolder(substr) {}
3390
matchCatch::Matchers::Impl::NSStringMatchers::EndsWith3391 virtual bool match(ExpressionType const& str) const
3392 {
3393 return (str != nil || m_substr == nil) &&
3394 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
3395 }
3396
toStringCatch::Matchers::Impl::NSStringMatchers::EndsWith3397 virtual std::string toString() const
3398 {
3399 return "ends with: " + Catch::toString(m_substr);
3400 }
3401 };
3402
3403 } // namespace NSStringMatchers
3404 } // namespace Impl
3405
3406 inline Impl::NSStringMatchers::Equals
Equals(NSString * substr)3407 Equals(NSString* substr) { return Impl::NSStringMatchers::Equals(substr); }
3408
3409 inline Impl::NSStringMatchers::Contains
Contains(NSString * substr)3410 Contains(NSString* substr) { return Impl::NSStringMatchers::Contains(substr); }
3411
3412 inline Impl::NSStringMatchers::StartsWith
StartsWith(NSString * substr)3413 StartsWith(NSString* substr) { return Impl::NSStringMatchers::StartsWith(substr); }
3414
3415 inline Impl::NSStringMatchers::EndsWith
EndsWith(NSString * substr)3416 EndsWith(NSString* substr) { return Impl::NSStringMatchers::EndsWith(substr); }
3417
3418 } // namespace Matchers
3419
3420 using namespace Matchers;
3421
3422 } // namespace Catch
3423
3424 ///////////////////////////////////////////////////////////////////////////////
3425 #define OC_TEST_CASE(name, desc) \
3426 +(NSString*)INTERNAL_CATCH_UNIQUE_NAME(Catch_Name_test) \
3427 { \
3428 return @name; \
3429 } \
3430 +(NSString*)INTERNAL_CATCH_UNIQUE_NAME(Catch_Description_test) \
3431 { \
3432 return @desc; \
3433 } \
3434 -(void)INTERNAL_CATCH_UNIQUE_NAME(Catch_TestCase_test)
3435
3436 #endif
3437
3438 #ifdef CATCH_IMPL
3439 // #included from: internal/catch_impl.hpp
3440 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
3441
3442 // Collect all the implementation files together here
3443 // These are the equivalent of what would usually be cpp files
3444
3445 #ifdef __clang__
3446 #pragma clang diagnostic push
3447 #pragma clang diagnostic ignored "-Wweak-vtables"
3448 #endif
3449
3450 // #included from: ../catch_session.hpp
3451 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
3452
3453 // #included from: internal/catch_commandline.hpp
3454 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3455
3456 // #included from: catch_config.hpp
3457 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3458
3459 // #included from: catch_test_spec_parser.hpp
3460 #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
3461
3462 #ifdef __clang__
3463 #pragma clang diagnostic push
3464 #pragma clang diagnostic ignored "-Wpadded"
3465 #endif
3466
3467 // #included from: catch_test_spec.hpp
3468 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
3469
3470 #ifdef __clang__
3471 #pragma clang diagnostic push
3472 #pragma clang diagnostic ignored "-Wpadded"
3473 #endif
3474
3475 // #included from: catch_wildcard_pattern.hpp
3476 #define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3477
3478 namespace Catch {
3479 class WildcardPattern
3480 {
3481 enum WildcardPosition
3482 {
3483 NoWildcard = 0,
3484 WildcardAtStart = 1,
3485 WildcardAtEnd = 2,
3486 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3487 };
3488
3489 public:
WildcardPattern(std::string const & pattern,CaseSensitive::Choice caseSensitivity)3490 WildcardPattern(std::string const& pattern, CaseSensitive::Choice caseSensitivity)
3491 : m_caseSensitivity(caseSensitivity),
3492 m_wildcard(NoWildcard),
3493 m_pattern(adjustCase(pattern))
3494 {
3495 if (startsWith(m_pattern, "*"))
3496 {
3497 m_pattern = m_pattern.substr(1);
3498 m_wildcard = WildcardAtStart;
3499 }
3500 if (endsWith(m_pattern, "*"))
3501 {
3502 m_pattern = m_pattern.substr(0, m_pattern.size() - 1);
3503 m_wildcard = static_cast<WildcardPosition>(m_wildcard | WildcardAtEnd);
3504 }
3505 }
3506 virtual ~WildcardPattern();
matches(std::string const & str) const3507 virtual bool matches(std::string const& str) const
3508 {
3509 switch (m_wildcard)
3510 {
3511 case NoWildcard:
3512 return m_pattern == adjustCase(str);
3513 case WildcardAtStart:
3514 return endsWith(adjustCase(str), m_pattern);
3515 case WildcardAtEnd:
3516 return startsWith(adjustCase(str), m_pattern);
3517 case WildcardAtBothEnds:
3518 return contains(adjustCase(str), m_pattern);
3519 }
3520
3521 #ifdef __clang__
3522 #pragma clang diagnostic push
3523 #pragma clang diagnostic ignored "-Wunreachable-code"
3524 #endif
3525 throw std::logic_error("Unknown enum");
3526 #ifdef __clang__
3527 #pragma clang diagnostic pop
3528 #endif
3529 }
3530
3531 private:
adjustCase(std::string const & str) const3532 std::string adjustCase(std::string const& str) const
3533 {
3534 return m_caseSensitivity == CaseSensitive::No ? toLower(str) : str;
3535 }
3536 CaseSensitive::Choice m_caseSensitivity;
3537 WildcardPosition m_wildcard;
3538 std::string m_pattern;
3539 };
3540 }
3541
3542 #include <string>
3543 #include <vector>
3544
3545 namespace Catch {
3546
3547 class TestSpec
3548 {
3549 struct Pattern : SharedImpl<>
3550 {
3551 virtual ~Pattern();
3552 virtual bool matches(TestCaseInfo const& testCase) const = 0;
3553 };
3554 class NamePattern : public Pattern
3555 {
3556 public:
NamePattern(std::string const & name)3557 NamePattern(std::string const& name)
3558 : m_wildcardPattern(toLower(name), CaseSensitive::No)
3559 {
3560 }
3561 virtual ~NamePattern();
matches(TestCaseInfo const & testCase) const3562 virtual bool matches(TestCaseInfo const& testCase) const
3563 {
3564 return m_wildcardPattern.matches(toLower(testCase.name));
3565 }
3566
3567 private:
3568 WildcardPattern m_wildcardPattern;
3569 };
3570
3571 class TagPattern : public Pattern
3572 {
3573 public:
TagPattern(std::string const & tag)3574 TagPattern(std::string const& tag) : m_tag(toLower(tag)) {}
3575 virtual ~TagPattern();
matches(TestCaseInfo const & testCase) const3576 virtual bool matches(TestCaseInfo const& testCase) const
3577 {
3578 return testCase.lcaseTags.find(m_tag) != testCase.lcaseTags.end();
3579 }
3580
3581 private:
3582 std::string m_tag;
3583 };
3584
3585 class ExcludedPattern : public Pattern
3586 {
3587 public:
ExcludedPattern(Ptr<Pattern> const & underlyingPattern)3588 ExcludedPattern(Ptr<Pattern> const& underlyingPattern) : m_underlyingPattern(underlyingPattern) {}
3589 virtual ~ExcludedPattern();
matches(TestCaseInfo const & testCase) const3590 virtual bool matches(TestCaseInfo const& testCase) const { return !m_underlyingPattern->matches(testCase); }
3591 private:
3592 Ptr<Pattern> m_underlyingPattern;
3593 };
3594
3595 struct Filter
3596 {
3597 std::vector<Ptr<Pattern>> m_patterns;
3598
matchesCatch::TestSpec::Filter3599 bool matches(TestCaseInfo const& testCase) const
3600 {
3601 // All patterns in a filter must match for the filter to be a match
3602 for (std::vector<Ptr<Pattern>>::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it)
3603 if (!(*it)->matches(testCase))
3604 return false;
3605 return true;
3606 }
3607 };
3608
3609 public:
hasFilters() const3610 bool hasFilters() const
3611 {
3612 return !m_filters.empty();
3613 }
matches(TestCaseInfo const & testCase) const3614 bool matches(TestCaseInfo const& testCase) const
3615 {
3616 // A TestSpec matches if any filter matches
3617 for (std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it)
3618 if (it->matches(testCase))
3619 return true;
3620 return false;
3621 }
3622
3623 private:
3624 std::vector<Filter> m_filters;
3625
3626 friend class TestSpecParser;
3627 };
3628 }
3629
3630 #ifdef __clang__
3631 #pragma clang diagnostic pop
3632 #endif
3633
3634 namespace Catch {
3635
3636 class TestSpecParser
3637 {
3638 enum Mode
3639 {
3640 None,
3641 Name,
3642 QuotedName,
3643 Tag
3644 };
3645 Mode m_mode;
3646 bool m_exclusion;
3647 std::size_t m_start, m_pos;
3648 std::string m_arg;
3649 TestSpec::Filter m_currentFilter;
3650 TestSpec m_testSpec;
3651 ITagAliasRegistry const* m_tagAliases;
3652
3653 public:
TestSpecParser(ITagAliasRegistry const & tagAliases)3654 TestSpecParser(ITagAliasRegistry const& tagAliases) : m_tagAliases(&tagAliases) {}
3655
parse(std::string const & arg)3656 TestSpecParser& parse(std::string const& arg)
3657 {
3658 m_mode = None;
3659 m_exclusion = false;
3660 m_start = std::string::npos;
3661 m_arg = m_tagAliases->expandAliases(arg);
3662 for (m_pos = 0; m_pos < m_arg.size(); ++m_pos)
3663 visitChar(m_arg[m_pos]);
3664 if (m_mode == Name)
3665 addPattern<TestSpec::NamePattern>();
3666 return *this;
3667 }
testSpec()3668 TestSpec testSpec()
3669 {
3670 addFilter();
3671 return m_testSpec;
3672 }
3673
3674 private:
visitChar(char c)3675 void visitChar(char c)
3676 {
3677 if (m_mode == None)
3678 {
3679 switch (c)
3680 {
3681 case ' ':
3682 return;
3683 case '~':
3684 m_exclusion = true;
3685 return;
3686 case '[':
3687 return startNewMode(Tag, ++m_pos);
3688 case '"':
3689 return startNewMode(QuotedName, ++m_pos);
3690 default:
3691 startNewMode(Name, m_pos);
3692 break;
3693 }
3694 }
3695 if (m_mode == Name)
3696 {
3697 if (c == ',')
3698 {
3699 addPattern<TestSpec::NamePattern>();
3700 addFilter();
3701 }
3702 else if (c == '[')
3703 {
3704 if (subString() == "exclude:")
3705 m_exclusion = true;
3706 else
3707 addPattern<TestSpec::NamePattern>();
3708 startNewMode(Tag, ++m_pos);
3709 }
3710 }
3711 else if (m_mode == QuotedName && c == '"')
3712 addPattern<TestSpec::NamePattern>();
3713 else if (m_mode == Tag && c == ']')
3714 addPattern<TestSpec::TagPattern>();
3715 }
startNewMode(Mode mode,std::size_t start)3716 void startNewMode(Mode mode, std::size_t start)
3717 {
3718 m_mode = mode;
3719 m_start = start;
3720 }
subString() const3721 std::string subString() const { return m_arg.substr(m_start, m_pos - m_start); }
3722 template <typename T>
addPattern()3723 void addPattern()
3724 {
3725 std::string token = subString();
3726 if (startsWith(token, "exclude:"))
3727 {
3728 m_exclusion = true;
3729 token = token.substr(8);
3730 }
3731 if (!token.empty())
3732 {
3733 Ptr<TestSpec::Pattern> pattern = new T(token);
3734 if (m_exclusion)
3735 pattern = new TestSpec::ExcludedPattern(pattern);
3736 m_currentFilter.m_patterns.push_back(pattern);
3737 }
3738 m_exclusion = false;
3739 m_mode = None;
3740 }
addFilter()3741 void addFilter()
3742 {
3743 if (!m_currentFilter.m_patterns.empty())
3744 {
3745 m_testSpec.m_filters.push_back(m_currentFilter);
3746 m_currentFilter = TestSpec::Filter();
3747 }
3748 }
3749 };
parseTestSpec(std::string const & arg)3750 inline TestSpec parseTestSpec(std::string const& arg)
3751 {
3752 return TestSpecParser(ITagAliasRegistry::get()).parse(arg).testSpec();
3753 }
3754
3755 } // namespace Catch
3756
3757 #ifdef __clang__
3758 #pragma clang diagnostic pop
3759 #endif
3760
3761 // #included from: catch_interfaces_config.h
3762 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3763
3764 #include <iostream>
3765 #include <string>
3766 #include <vector>
3767
3768 namespace Catch {
3769
3770 struct Verbosity
3771 {
3772 enum Level
3773 {
3774 NoOutput = 0,
3775 Quiet,
3776 Normal
3777 };
3778 };
3779
3780 struct WarnAbout
3781 {
3782 enum What
3783 {
3784 Nothing = 0x00,
3785 NoAssertions = 0x01
3786 };
3787 };
3788
3789 struct ShowDurations
3790 {
3791 enum OrNot
3792 {
3793 DefaultForReporter,
3794 Always,
3795 Never
3796 };
3797 };
3798 struct RunTests
3799 {
3800 enum InWhatOrder
3801 {
3802 InDeclarationOrder,
3803 InLexicographicalOrder,
3804 InRandomOrder
3805 };
3806 };
3807
3808 class TestSpec;
3809
3810 struct IConfig : IShared
3811 {
3812
3813 virtual ~IConfig();
3814
3815 virtual bool allowThrows() const = 0;
3816 virtual std::ostream& stream() const = 0;
3817 virtual std::string name() const = 0;
3818 virtual bool includeSuccessfulResults() const = 0;
3819 virtual bool shouldDebugBreak() const = 0;
3820 virtual bool warnAboutMissingAssertions() const = 0;
3821 virtual int abortAfter() const = 0;
3822 virtual bool showInvisibles() const = 0;
3823 virtual ShowDurations::OrNot showDurations() const = 0;
3824 virtual TestSpec const& testSpec() const = 0;
3825 virtual RunTests::InWhatOrder runOrder() const = 0;
3826 virtual unsigned int rngSeed() const = 0;
3827 virtual bool forceColour() const = 0;
3828 };
3829 }
3830
3831 // #included from: catch_stream.h
3832 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3833
3834 // #included from: catch_streambuf.h
3835 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
3836
3837 #include <streambuf>
3838
3839 namespace Catch {
3840
3841 class StreamBufBase : public std::streambuf
3842 {
3843 public:
3844 virtual ~StreamBufBase() CATCH_NOEXCEPT;
3845 };
3846 }
3847
3848 #include <fstream>
3849 #include <ostream>
3850 #include <streambuf>
3851
3852 namespace Catch {
3853
3854 std::ostream& cout();
3855 std::ostream& cerr();
3856
3857 struct IStream
3858 {
3859 virtual ~IStream() CATCH_NOEXCEPT;
3860 virtual std::ostream& stream() const = 0;
3861 };
3862
3863 class FileStream : public IStream
3864 {
3865 mutable std::ofstream m_ofs;
3866
3867 public:
3868 FileStream(std::string const& filename);
3869 virtual ~FileStream() CATCH_NOEXCEPT;
3870
3871 public: // IStream
3872 virtual std::ostream& stream() const CATCH_OVERRIDE;
3873 };
3874
3875 class CoutStream : public IStream
3876 {
3877 mutable std::ostream m_os;
3878
3879 public:
3880 CoutStream();
3881 virtual ~CoutStream() CATCH_NOEXCEPT;
3882
3883 public: // IStream
3884 virtual std::ostream& stream() const CATCH_OVERRIDE;
3885 };
3886
3887 class DebugOutStream : public IStream
3888 {
3889 std::auto_ptr<StreamBufBase> m_streamBuf;
3890 mutable std::ostream m_os;
3891
3892 public:
3893 DebugOutStream();
3894 virtual ~DebugOutStream() CATCH_NOEXCEPT;
3895
3896 public: // IStream
3897 virtual std::ostream& stream() const CATCH_OVERRIDE;
3898 };
3899 }
3900
3901 #include <ctime>
3902 #include <iostream>
3903 #include <memory>
3904 #include <string>
3905 #include <vector>
3906
3907 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
3908 #define CATCH_CONFIG_CONSOLE_WIDTH 80
3909 #endif
3910
3911 namespace Catch {
3912
3913 struct ConfigData
3914 {
3915
ConfigDataCatch::ConfigData3916 ConfigData()
3917 : listTests(false),
3918 listTags(false),
3919 listReporters(false),
3920 listTestNamesOnly(false),
3921 showSuccessfulTests(false),
3922 shouldDebugBreak(false),
3923 noThrow(false),
3924 showHelp(false),
3925 showInvisibles(false),
3926 forceColour(false),
3927 filenamesAsTags(false),
3928 abortAfter(-1),
3929 rngSeed(0),
3930 verbosity(Verbosity::Normal),
3931 warnings(WarnAbout::Nothing),
3932 showDurations(ShowDurations::DefaultForReporter),
3933 runOrder(RunTests::InDeclarationOrder)
3934 {
3935 }
3936
3937 bool listTests;
3938 bool listTags;
3939 bool listReporters;
3940 bool listTestNamesOnly;
3941
3942 bool showSuccessfulTests;
3943 bool shouldDebugBreak;
3944 bool noThrow;
3945 bool showHelp;
3946 bool showInvisibles;
3947 bool forceColour;
3948 bool filenamesAsTags;
3949
3950 int abortAfter;
3951 unsigned int rngSeed;
3952
3953 Verbosity::Level verbosity;
3954 WarnAbout::What warnings;
3955 ShowDurations::OrNot showDurations;
3956 RunTests::InWhatOrder runOrder;
3957
3958 std::string outputFilename;
3959 std::string name;
3960 std::string processName;
3961
3962 std::vector<std::string> reporterNames;
3963 std::vector<std::string> testsOrTags;
3964 };
3965
3966 class Config : public SharedImpl<IConfig>
3967 {
3968 private:
3969 Config(Config const& other);
3970 Config& operator=(Config const& other);
3971 virtual void dummy();
3972
3973 public:
Config()3974 Config()
3975 {
3976 }
3977
Config(ConfigData const & data)3978 Config(ConfigData const& data)
3979 : m_data(data),
3980 m_stream(openStream())
3981 {
3982 if (!data.testsOrTags.empty())
3983 {
3984 TestSpecParser parser(ITagAliasRegistry::get());
3985 for (std::size_t i = 0; i < data.testsOrTags.size(); ++i)
3986 parser.parse(data.testsOrTags[i]);
3987 m_testSpec = parser.testSpec();
3988 }
3989 }
3990
~Config()3991 virtual ~Config()
3992 {
3993 }
3994
getFilename() const3995 std::string const& getFilename() const
3996 {
3997 return m_data.outputFilename;
3998 }
3999
listTests() const4000 bool listTests() const { return m_data.listTests; }
listTestNamesOnly() const4001 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
listTags() const4002 bool listTags() const { return m_data.listTags; }
listReporters() const4003 bool listReporters() const { return m_data.listReporters; }
4004
getProcessName() const4005 std::string getProcessName() const { return m_data.processName; }
4006
shouldDebugBreak() const4007 bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
4008
getReporterNames() const4009 std::vector<std::string> getReporterNames() const { return m_data.reporterNames; }
4010
abortAfter() const4011 int abortAfter() const { return m_data.abortAfter; }
4012
testSpec() const4013 TestSpec const& testSpec() const { return m_testSpec; }
4014
showHelp() const4015 bool showHelp() const { return m_data.showHelp; }
showInvisibles() const4016 bool showInvisibles() const { return m_data.showInvisibles; }
4017
4018 // IConfig interface
allowThrows() const4019 virtual bool allowThrows() const { return !m_data.noThrow; }
stream() const4020 virtual std::ostream& stream() const { return m_stream->stream(); }
name() const4021 virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
includeSuccessfulResults() const4022 virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
warnAboutMissingAssertions() const4023 virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
showDurations() const4024 virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
runOrder() const4025 virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
rngSeed() const4026 virtual unsigned int rngSeed() const { return m_data.rngSeed; }
forceColour() const4027 virtual bool forceColour() const { return m_data.forceColour; }
4028
4029 private:
openStream()4030 IStream const* openStream()
4031 {
4032 if (m_data.outputFilename.empty())
4033 return new CoutStream();
4034 else if (m_data.outputFilename[0] == '%')
4035 {
4036 if (m_data.outputFilename == "%debug")
4037 return new DebugOutStream();
4038 else
4039 throw std::domain_error("Unrecognised stream: " + m_data.outputFilename);
4040 }
4041 else
4042 return new FileStream(m_data.outputFilename);
4043 }
4044 ConfigData m_data;
4045
4046 std::auto_ptr<IStream const> m_stream;
4047 TestSpec m_testSpec;
4048 };
4049
4050 } // end namespace Catch
4051
4052 // #included from: catch_clara.h
4053 #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
4054
4055 // Use Catch's value for console width (store Clara's off to the side, if present)
4056 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
4057 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
4058 #undef CLARA_CONFIG_CONSOLE_WIDTH
4059 #endif
4060 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4061
4062 // Declare Clara inside the Catch namespace
4063 #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
4064 // #included from: ../external/clara.h
4065
4066 // Only use header guard if we are not using an outer namespace
4067 #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
4068
4069 #ifndef STITCH_CLARA_OPEN_NAMESPACE
4070 #define TWOBLUECUBES_CLARA_H_INCLUDED
4071 #define STITCH_CLARA_OPEN_NAMESPACE
4072 #define STITCH_CLARA_CLOSE_NAMESPACE
4073 #else
4074 #define STITCH_CLARA_CLOSE_NAMESPACE }
4075 #endif
4076
4077 #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
4078
4079 // ----------- #included from tbc_text_format.h -----------
4080
4081 // Only use header guard if we are not using an outer namespace
4082 #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
4083 #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4084 #define TBC_TEXT_FORMAT_H_INCLUDED
4085 #endif
4086
4087 #include <sstream>
4088 #include <string>
4089 #include <vector>
4090
4091 // Use optional outer namespace
4092 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4093 namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4094 #endif
4095
4096 namespace Tbc {
4097
4098 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4099 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4100 #else
4101 const unsigned int consoleWidth = 80;
4102 #endif
4103
4104 struct TextAttributes
4105 {
TextAttributesSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4106 TextAttributes()
4107 : initialIndent(std::string::npos),
4108 indent(0),
4109 width(consoleWidth - 1),
4110 tabChar('\t')
4111 {
4112 }
4113
setInitialIndentSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4114 TextAttributes& setInitialIndent(std::size_t _value)
4115 {
4116 initialIndent = _value;
4117 return *this;
4118 }
setIndentSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4119 TextAttributes& setIndent(std::size_t _value)
4120 {
4121 indent = _value;
4122 return *this;
4123 }
setWidthSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4124 TextAttributes& setWidth(std::size_t _value)
4125 {
4126 width = _value;
4127 return *this;
4128 }
setTabCharSTITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes4129 TextAttributes& setTabChar(char _value)
4130 {
4131 tabChar = _value;
4132 return *this;
4133 }
4134
4135 std::size_t initialIndent; // indent of first line, or npos
4136 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
4137 std::size_t width; // maximum width of text, including indent. Longer text will wrap
4138 char tabChar; // If this char is seen the indent is changed to current pos
4139 };
4140
4141 class Text
4142 {
4143 public:
Text(std::string const & _str,TextAttributes const & _attr=TextAttributes ())4144 Text(std::string const& _str, TextAttributes const& _attr = TextAttributes())
4145 : attr(_attr)
4146 {
4147 std::string wrappableChars = " [({.,/|\\-";
4148 std::size_t indent = _attr.initialIndent != std::string::npos
4149 ? _attr.initialIndent
4150 : _attr.indent;
4151 std::string remainder = _str;
4152
4153 while (!remainder.empty())
4154 {
4155 if (lines.size() >= 1000)
4156 {
4157 lines.push_back("... message truncated due to excessive size");
4158 return;
4159 }
4160 std::size_t tabPos = std::string::npos;
4161 std::size_t width = (std::min)(remainder.size(), _attr.width - indent);
4162 std::size_t pos = remainder.find_first_of('\n');
4163 if (pos <= width)
4164 {
4165 width = pos;
4166 }
4167 pos = remainder.find_last_of(_attr.tabChar, width);
4168 if (pos != std::string::npos)
4169 {
4170 tabPos = pos;
4171 if (remainder[width] == '\n')
4172 width--;
4173 remainder = remainder.substr(0, tabPos) + remainder.substr(tabPos + 1);
4174 }
4175
4176 if (width == remainder.size())
4177 {
4178 spliceLine(indent, remainder, width);
4179 }
4180 else if (remainder[width] == '\n')
4181 {
4182 spliceLine(indent, remainder, width);
4183 if (width <= 1 || remainder.size() != 1)
4184 remainder = remainder.substr(1);
4185 indent = _attr.indent;
4186 }
4187 else
4188 {
4189 pos = remainder.find_last_of(wrappableChars, width);
4190 if (pos != std::string::npos && pos > 0)
4191 {
4192 spliceLine(indent, remainder, pos);
4193 if (remainder[0] == ' ')
4194 remainder = remainder.substr(1);
4195 }
4196 else
4197 {
4198 spliceLine(indent, remainder, width - 1);
4199 lines.back() += "-";
4200 }
4201 if (lines.size() == 1)
4202 indent = _attr.indent;
4203 if (tabPos != std::string::npos)
4204 indent += tabPos;
4205 }
4206 }
4207 }
4208
spliceLine(std::size_t _indent,std::string & _remainder,std::size_t _pos)4209 void spliceLine(std::size_t _indent, std::string& _remainder, std::size_t _pos)
4210 {
4211 lines.push_back(std::string(_indent, ' ') + _remainder.substr(0, _pos));
4212 _remainder = _remainder.substr(_pos);
4213 }
4214
4215 typedef std::vector<std::string>::const_iterator const_iterator;
4216
begin() const4217 const_iterator begin() const { return lines.begin(); }
end() const4218 const_iterator end() const { return lines.end(); }
last() const4219 std::string const& last() const { return lines.back(); }
size() const4220 std::size_t size() const { return lines.size(); }
operator [](std::size_t _index) const4221 std::string const& operator[](std::size_t _index) const { return lines[_index]; }
toString() const4222 std::string toString() const
4223 {
4224 std::ostringstream oss;
4225 oss << *this;
4226 return oss.str();
4227 }
4228
operator <<(std::ostream & _stream,Text const & _text)4229 inline friend std::ostream& operator<<(std::ostream& _stream, Text const& _text)
4230 {
4231 for (Text::const_iterator it = _text.begin(), itEnd = _text.end();
4232 it != itEnd; ++it)
4233 {
4234 if (it != _text.begin())
4235 _stream << "\n";
4236 _stream << *it;
4237 }
4238 return _stream;
4239 }
4240
4241 private:
4242 std::string str;
4243 TextAttributes attr;
4244 std::vector<std::string> lines;
4245 };
4246
4247 } // end namespace Tbc
4248
4249 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4250 } // end outer namespace
4251 #endif
4252
4253 #endif // TBC_TEXT_FORMAT_H_INCLUDED
4254
4255 // ----------- end of #include from tbc_text_format.h -----------
4256 // ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h
4257
4258 #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
4259
4260 #include <algorithm>
4261 #include <map>
4262 #include <memory>
4263 #include <stdexcept>
4264
4265 // Use optional outer namespace
4266 #ifdef STITCH_CLARA_OPEN_NAMESPACE
4267 STITCH_CLARA_OPEN_NAMESPACE
4268 #endif
4269
4270 namespace Clara {
4271
4272 struct UnpositionalTag
4273 {
4274 };
4275
4276 extern UnpositionalTag _;
4277
4278 #ifdef CLARA_CONFIG_MAIN
4279 UnpositionalTag _;
4280 #endif
4281
4282 namespace Detail {
4283
4284 #ifdef CLARA_CONSOLE_WIDTH
4285 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
4286 #else
4287 const unsigned int consoleWidth = 80;
4288 #endif
4289
4290 using namespace Tbc;
4291
startsWith(std::string const & str,std::string const & prefix)4292 inline bool startsWith(std::string const& str, std::string const& prefix)
4293 {
4294 return str.size() >= prefix.size() && str.substr(0, prefix.size()) == prefix;
4295 }
4296
4297 template <typename T>
4298 struct RemoveConstRef
4299 {
4300 typedef T type;
4301 };
4302 template <typename T>
4303 struct RemoveConstRef<T&>
4304 {
4305 typedef T type;
4306 };
4307 template <typename T>
4308 struct RemoveConstRef<T const&>
4309 {
4310 typedef T type;
4311 };
4312 template <typename T>
4313 struct RemoveConstRef<T const>
4314 {
4315 typedef T type;
4316 };
4317
4318 template <typename T>
4319 struct IsBool
4320 {
4321 static const bool value = false;
4322 };
4323 template <>
4324 struct IsBool<bool>
4325 {
4326 static const bool value = true;
4327 };
4328
4329 template <typename T>
convertInto(std::string const & _source,T & _dest)4330 void convertInto(std::string const& _source, T& _dest)
4331 {
4332 std::stringstream ss;
4333 ss << _source;
4334 ss >> _dest;
4335 if (ss.fail())
4336 throw std::runtime_error("Unable to convert " + _source + " to destination type");
4337 }
convertInto(std::string const & _source,std::string & _dest)4338 inline void convertInto(std::string const& _source, std::string& _dest)
4339 {
4340 _dest = _source;
4341 }
convertInto(std::string const & _source,bool & _dest)4342 inline void convertInto(std::string const& _source, bool& _dest)
4343 {
4344 std::string sourceLC = _source;
4345 std::transform(sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower);
4346 if (sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on")
4347 _dest = true;
4348 else if (sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off")
4349 _dest = false;
4350 else
4351 throw std::runtime_error("Expected a boolean value but did not recognise:\n '" + _source + "'");
4352 }
convertInto(bool _source,bool & _dest)4353 inline void convertInto(bool _source, bool& _dest)
4354 {
4355 _dest = _source;
4356 }
4357 template <typename T>
convertInto(bool,T &)4358 inline void convertInto(bool, T&)
4359 {
4360 throw std::runtime_error("Invalid conversion");
4361 }
4362
4363 template <typename ConfigT>
4364 struct IArgFunction
4365 {
~IArgFunctionClara::Detail::IArgFunction4366 virtual ~IArgFunction() {}
4367 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4368 IArgFunction() = default;
4369 IArgFunction(IArgFunction const&) = default;
4370 #endif
4371 virtual void set(ConfigT& config, std::string const& value) const = 0;
4372 virtual void setFlag(ConfigT& config) const = 0;
4373 virtual bool takesArg() const = 0;
4374 virtual IArgFunction* clone() const = 0;
4375 };
4376
4377 template <typename ConfigT>
4378 class BoundArgFunction
4379 {
4380 public:
BoundArgFunction()4381 BoundArgFunction() : functionObj(CATCH_NULL) {}
BoundArgFunction(IArgFunction<ConfigT> * _functionObj)4382 BoundArgFunction(IArgFunction<ConfigT>* _functionObj) : functionObj(_functionObj) {}
BoundArgFunction(BoundArgFunction const & other)4383 BoundArgFunction(BoundArgFunction const& other) : functionObj(other.functionObj ? other.functionObj->clone() : CATCH_NULL) {}
operator =(BoundArgFunction const & other)4384 BoundArgFunction& operator=(BoundArgFunction const& other)
4385 {
4386 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CATCH_NULL;
4387 delete functionObj;
4388 functionObj = newFunctionObj;
4389 return *this;
4390 }
~BoundArgFunction()4391 ~BoundArgFunction() { delete functionObj; }
4392
set(ConfigT & config,std::string const & value) const4393 void set(ConfigT& config, std::string const& value) const
4394 {
4395 functionObj->set(config, value);
4396 }
setFlag(ConfigT & config) const4397 void setFlag(ConfigT& config) const
4398 {
4399 functionObj->setFlag(config);
4400 }
takesArg() const4401 bool takesArg() const { return functionObj->takesArg(); }
4402
isSet() const4403 bool isSet() const
4404 {
4405 return functionObj != CATCH_NULL;
4406 }
4407
4408 private:
4409 IArgFunction<ConfigT>* functionObj;
4410 };
4411
4412 template <typename C>
4413 struct NullBinder : IArgFunction<C>
4414 {
setClara::Detail::NullBinder4415 virtual void set(C&, std::string const&) const {}
setFlagClara::Detail::NullBinder4416 virtual void setFlag(C&) const {}
takesArgClara::Detail::NullBinder4417 virtual bool takesArg() const { return true; }
cloneClara::Detail::NullBinder4418 virtual IArgFunction<C>* clone() const { return new NullBinder(*this); }
4419 };
4420
4421 template <typename C, typename M>
4422 struct BoundDataMember : IArgFunction<C>
4423 {
BoundDataMemberClara::Detail::BoundDataMember4424 BoundDataMember(M C::*_member) : member(_member) {}
setClara::Detail::BoundDataMember4425 virtual void set(C& p, std::string const& stringValue) const
4426 {
4427 convertInto(stringValue, p.*member);
4428 }
setFlagClara::Detail::BoundDataMember4429 virtual void setFlag(C& p) const
4430 {
4431 convertInto(true, p.*member);
4432 }
takesArgClara::Detail::BoundDataMember4433 virtual bool takesArg() const { return !IsBool<M>::value; }
cloneClara::Detail::BoundDataMember4434 virtual IArgFunction<C>* clone() const { return new BoundDataMember(*this); }
4435 M C::*member;
4436 };
4437 template <typename C, typename M>
4438 struct BoundUnaryMethod : IArgFunction<C>
4439 {
BoundUnaryMethodClara::Detail::BoundUnaryMethod4440 BoundUnaryMethod(void (C::*_member)(M)) : member(_member) {}
setClara::Detail::BoundUnaryMethod4441 virtual void set(C& p, std::string const& stringValue) const
4442 {
4443 typename RemoveConstRef<M>::type value;
4444 convertInto(stringValue, value);
4445 (p.*member)(value);
4446 }
setFlagClara::Detail::BoundUnaryMethod4447 virtual void setFlag(C& p) const
4448 {
4449 typename RemoveConstRef<M>::type value;
4450 convertInto(true, value);
4451 (p.*member)(value);
4452 }
takesArgClara::Detail::BoundUnaryMethod4453 virtual bool takesArg() const { return !IsBool<M>::value; }
cloneClara::Detail::BoundUnaryMethod4454 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod(*this); }
4455 void (C::*member)(M);
4456 };
4457 template <typename C>
4458 struct BoundNullaryMethod : IArgFunction<C>
4459 {
BoundNullaryMethodClara::Detail::BoundNullaryMethod4460 BoundNullaryMethod(void (C::*_member)()) : member(_member) {}
setClara::Detail::BoundNullaryMethod4461 virtual void set(C& p, std::string const& stringValue) const
4462 {
4463 bool value;
4464 convertInto(stringValue, value);
4465 if (value)
4466 (p.*member)();
4467 }
setFlagClara::Detail::BoundNullaryMethod4468 virtual void setFlag(C& p) const
4469 {
4470 (p.*member)();
4471 }
takesArgClara::Detail::BoundNullaryMethod4472 virtual bool takesArg() const { return false; }
cloneClara::Detail::BoundNullaryMethod4473 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod(*this); }
4474 void (C::*member)();
4475 };
4476
4477 template <typename C>
4478 struct BoundUnaryFunction : IArgFunction<C>
4479 {
BoundUnaryFunctionClara::Detail::BoundUnaryFunction4480 BoundUnaryFunction(void (*_function)(C&)) : function(_function) {}
setClara::Detail::BoundUnaryFunction4481 virtual void set(C& obj, std::string const& stringValue) const
4482 {
4483 bool value;
4484 convertInto(stringValue, value);
4485 if (value)
4486 function(obj);
4487 }
setFlagClara::Detail::BoundUnaryFunction4488 virtual void setFlag(C& p) const
4489 {
4490 function(p);
4491 }
takesArgClara::Detail::BoundUnaryFunction4492 virtual bool takesArg() const { return false; }
cloneClara::Detail::BoundUnaryFunction4493 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction(*this); }
4494 void (*function)(C&);
4495 };
4496
4497 template <typename C, typename T>
4498 struct BoundBinaryFunction : IArgFunction<C>
4499 {
BoundBinaryFunctionClara::Detail::BoundBinaryFunction4500 BoundBinaryFunction(void (*_function)(C&, T)) : function(_function) {}
setClara::Detail::BoundBinaryFunction4501 virtual void set(C& obj, std::string const& stringValue) const
4502 {
4503 typename RemoveConstRef<T>::type value;
4504 convertInto(stringValue, value);
4505 function(obj, value);
4506 }
setFlagClara::Detail::BoundBinaryFunction4507 virtual void setFlag(C& obj) const
4508 {
4509 typename RemoveConstRef<T>::type value;
4510 convertInto(true, value);
4511 function(obj, value);
4512 }
takesArgClara::Detail::BoundBinaryFunction4513 virtual bool takesArg() const { return !IsBool<T>::value; }
cloneClara::Detail::BoundBinaryFunction4514 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction(*this); }
4515 void (*function)(C&, T);
4516 };
4517
4518 } // namespace Detail
4519
4520 struct Parser
4521 {
ParserClara::Parser4522 Parser() : separators(" \t=:") {}
4523
4524 struct Token
4525 {
4526 enum Type
4527 {
4528 Positional,
4529 ShortOpt,
4530 LongOpt
4531 };
TokenClara::Parser::Token4532 Token(Type _type, std::string const& _data) : type(_type), data(_data) {}
4533 Type type;
4534 std::string data;
4535 };
4536
parseIntoTokensClara::Parser4537 void parseIntoTokens(int argc, char const* const* argv, std::vector<Parser::Token>& tokens) const
4538 {
4539 const std::string doubleDash = "--";
4540 for (int i = 1; i < argc && argv[i] != doubleDash; ++i)
4541 parseIntoTokens(argv[i], tokens);
4542 }
parseIntoTokensClara::Parser4543 void parseIntoTokens(std::string arg, std::vector<Parser::Token>& tokens) const
4544 {
4545 while (!arg.empty())
4546 {
4547 Parser::Token token(Parser::Token::Positional, arg);
4548 arg = "";
4549 if (token.data[0] == '-')
4550 {
4551 if (token.data.size() > 1 && token.data[1] == '-')
4552 {
4553 token = Parser::Token(Parser::Token::LongOpt, token.data.substr(2));
4554 }
4555 else
4556 {
4557 token = Parser::Token(Parser::Token::ShortOpt, token.data.substr(1));
4558 if (token.data.size() > 1 && separators.find(token.data[1]) == std::string::npos)
4559 {
4560 arg = "-" + token.data.substr(1);
4561 token.data = token.data.substr(0, 1);
4562 }
4563 }
4564 }
4565 if (token.type != Parser::Token::Positional)
4566 {
4567 std::size_t pos = token.data.find_first_of(separators);
4568 if (pos != std::string::npos)
4569 {
4570 arg = token.data.substr(pos + 1);
4571 token.data = token.data.substr(0, pos);
4572 }
4573 }
4574 tokens.push_back(token);
4575 }
4576 }
4577 std::string separators;
4578 };
4579
4580 template <typename ConfigT>
4581 struct CommonArgProperties
4582 {
CommonArgPropertiesClara::CommonArgProperties4583 CommonArgProperties() {}
CommonArgPropertiesClara::CommonArgProperties4584 CommonArgProperties(Detail::BoundArgFunction<ConfigT> const& _boundField) : boundField(_boundField) {}
4585
4586 Detail::BoundArgFunction<ConfigT> boundField;
4587 std::string description;
4588 std::string detail;
4589 std::string placeholder; // Only value if boundField takes an arg
4590
takesArgClara::CommonArgProperties4591 bool takesArg() const
4592 {
4593 return !placeholder.empty();
4594 }
validateClara::CommonArgProperties4595 void validate() const
4596 {
4597 if (!boundField.isSet())
4598 throw std::logic_error("option not bound");
4599 }
4600 };
4601 struct OptionArgProperties
4602 {
4603 std::vector<std::string> shortNames;
4604 std::string longName;
4605
hasShortNameClara::OptionArgProperties4606 bool hasShortName(std::string const& shortName) const
4607 {
4608 return std::find(shortNames.begin(), shortNames.end(), shortName) != shortNames.end();
4609 }
hasLongNameClara::OptionArgProperties4610 bool hasLongName(std::string const& _longName) const
4611 {
4612 return _longName == longName;
4613 }
4614 };
4615 struct PositionalArgProperties
4616 {
PositionalArgPropertiesClara::PositionalArgProperties4617 PositionalArgProperties() : position(-1) {}
4618 int position; // -1 means non-positional (floating)
4619
isFixedPositionalClara::PositionalArgProperties4620 bool isFixedPositional() const
4621 {
4622 return position != -1;
4623 }
4624 };
4625
4626 template <typename ConfigT>
4627 class CommandLine
4628 {
4629
4630 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties
4631 {
ArgClara::CommandLine::Arg4632 Arg() {}
ArgClara::CommandLine::Arg4633 Arg(Detail::BoundArgFunction<ConfigT> const& _boundField) : CommonArgProperties<ConfigT>(_boundField) {}
4634
4635 using CommonArgProperties<ConfigT>::placeholder; // !TBD
4636
dbgNameClara::CommandLine::Arg4637 std::string dbgName() const
4638 {
4639 if (!longName.empty())
4640 return "--" + longName;
4641 if (!shortNames.empty())
4642 return "-" + shortNames[0];
4643 return "positional args";
4644 }
commandsClara::CommandLine::Arg4645 std::string commands() const
4646 {
4647 std::ostringstream oss;
4648 bool first = true;
4649 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4650 for (; it != itEnd; ++it)
4651 {
4652 if (first)
4653 first = false;
4654 else
4655 oss << ", ";
4656 oss << "-" << *it;
4657 }
4658 if (!longName.empty())
4659 {
4660 if (!first)
4661 oss << ", ";
4662 oss << "--" << longName;
4663 }
4664 if (!placeholder.empty())
4665 oss << " <" << placeholder << ">";
4666 return oss.str();
4667 }
4668 };
4669
4670 typedef CATCH_AUTO_PTR(Arg) ArgAutoPtr;
4671
addOptName(Arg & arg,std::string const & optName)4672 friend void addOptName(Arg& arg, std::string const& optName)
4673 {
4674 if (optName.empty())
4675 return;
4676 if (Detail::startsWith(optName, "--"))
4677 {
4678 if (!arg.longName.empty())
4679 throw std::logic_error("Only one long opt may be specified. '" + arg.longName + "' already specified, now attempting to add '" + optName + "'");
4680 arg.longName = optName.substr(2);
4681 }
4682 else if (Detail::startsWith(optName, "-"))
4683 arg.shortNames.push_back(optName.substr(1));
4684 else
4685 throw std::logic_error("option must begin with - or --. Option was: '" + optName + "'");
4686 }
setPositionalArg(Arg & arg,int position)4687 friend void setPositionalArg(Arg& arg, int position)
4688 {
4689 arg.position = position;
4690 }
4691
4692 class ArgBuilder
4693 {
4694 public:
ArgBuilder(Arg * arg)4695 ArgBuilder(Arg* arg) : m_arg(arg) {}
4696
4697 // Bind a non-boolean data member (requires placeholder string)
4698 template <typename C, typename M>
bind(M C::* field,std::string const & placeholder)4699 void bind(M C::*field, std::string const& placeholder)
4700 {
4701 m_arg->boundField = new Detail::BoundDataMember<C, M>(field);
4702 m_arg->placeholder = placeholder;
4703 }
4704 // Bind a boolean data member (no placeholder required)
4705 template <typename C>
bind(bool C::* field)4706 void bind(bool C::*field)
4707 {
4708 m_arg->boundField = new Detail::BoundDataMember<C, bool>(field);
4709 }
4710
4711 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
4712 template <typename C, typename M>
bind(void (C::* unaryMethod)(M),std::string const & placeholder)4713 void bind(void (C::*unaryMethod)(M), std::string const& placeholder)
4714 {
4715 m_arg->boundField = new Detail::BoundUnaryMethod<C, M>(unaryMethod);
4716 m_arg->placeholder = placeholder;
4717 }
4718
4719 // Bind a method taking a single, boolean argument (no placeholder string required)
4720 template <typename C>
bind(void (C::* unaryMethod)(bool))4721 void bind(void (C::*unaryMethod)(bool))
4722 {
4723 m_arg->boundField = new Detail::BoundUnaryMethod<C, bool>(unaryMethod);
4724 }
4725
4726 // Bind a method that takes no arguments (will be called if opt is present)
4727 template <typename C>
bind(void (C::* nullaryMethod)())4728 void bind(void (C::*nullaryMethod)())
4729 {
4730 m_arg->boundField = new Detail::BoundNullaryMethod<C>(nullaryMethod);
4731 }
4732
4733 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
4734 template <typename C>
bind(void (* unaryFunction)(C &))4735 void bind(void (*unaryFunction)(C&))
4736 {
4737 m_arg->boundField = new Detail::BoundUnaryFunction<C>(unaryFunction);
4738 }
4739
4740 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
4741 template <typename C, typename T>
bind(void (* binaryFunction)(C &,T),std::string const & placeholder)4742 void bind(void (*binaryFunction)(C&, T), std::string const& placeholder)
4743 {
4744 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>(binaryFunction);
4745 m_arg->placeholder = placeholder;
4746 }
4747
describe(std::string const & description)4748 ArgBuilder& describe(std::string const& description)
4749 {
4750 m_arg->description = description;
4751 return *this;
4752 }
detail(std::string const & _detail)4753 ArgBuilder& detail(std::string const& _detail)
4754 {
4755 m_arg->detail = _detail;
4756 return *this;
4757 }
4758
4759 protected:
4760 Arg* m_arg;
4761 };
4762
4763 class OptBuilder : public ArgBuilder
4764 {
4765 public:
OptBuilder(Arg * arg)4766 OptBuilder(Arg* arg) : ArgBuilder(arg) {}
OptBuilder(OptBuilder & other)4767 OptBuilder(OptBuilder& other) : ArgBuilder(other) {}
4768
operator [](std::string const & optName)4769 OptBuilder& operator[](std::string const& optName)
4770 {
4771 addOptName(*ArgBuilder::m_arg, optName);
4772 return *this;
4773 }
4774 };
4775
4776 public:
CommandLine()4777 CommandLine()
4778 : m_boundProcessName(new Detail::NullBinder<ConfigT>()),
4779 m_highestSpecifiedArgPosition(0),
4780 m_throwOnUnrecognisedTokens(false)
4781 {
4782 }
CommandLine(CommandLine const & other)4783 CommandLine(CommandLine const& other)
4784 : m_boundProcessName(other.m_boundProcessName),
4785 m_options(other.m_options),
4786 m_positionalArgs(other.m_positionalArgs),
4787 m_highestSpecifiedArgPosition(other.m_highestSpecifiedArgPosition),
4788 m_throwOnUnrecognisedTokens(other.m_throwOnUnrecognisedTokens)
4789 {
4790 if (other.m_floatingArg.get())
4791 m_floatingArg.reset(new Arg(*other.m_floatingArg));
4792 }
4793
setThrowOnUnrecognisedTokens(bool shouldThrow=true)4794 CommandLine& setThrowOnUnrecognisedTokens(bool shouldThrow = true)
4795 {
4796 m_throwOnUnrecognisedTokens = shouldThrow;
4797 return *this;
4798 }
4799
operator [](std::string const & optName)4800 OptBuilder operator[](std::string const& optName)
4801 {
4802 m_options.push_back(Arg());
4803 addOptName(m_options.back(), optName);
4804 OptBuilder builder(&m_options.back());
4805 return builder;
4806 }
4807
operator [](int position)4808 ArgBuilder operator[](int position)
4809 {
4810 m_positionalArgs.insert(std::make_pair(position, Arg()));
4811 if (position > m_highestSpecifiedArgPosition)
4812 m_highestSpecifiedArgPosition = position;
4813 setPositionalArg(m_positionalArgs[position], position);
4814 ArgBuilder builder(&m_positionalArgs[position]);
4815 return builder;
4816 }
4817
4818 // Invoke this with the _ instance
operator [](UnpositionalTag)4819 ArgBuilder operator[](UnpositionalTag)
4820 {
4821 if (m_floatingArg.get())
4822 throw std::logic_error("Only one unpositional argument can be added");
4823 m_floatingArg.reset(new Arg());
4824 ArgBuilder builder(m_floatingArg.get());
4825 return builder;
4826 }
4827
4828 template <typename C, typename M>
bindProcessName(M C::* field)4829 void bindProcessName(M C::*field)
4830 {
4831 m_boundProcessName = new Detail::BoundDataMember<C, M>(field);
4832 }
4833 template <typename C, typename M>
bindProcessName(void (C::* _unaryMethod)(M))4834 void bindProcessName(void (C::*_unaryMethod)(M))
4835 {
4836 m_boundProcessName = new Detail::BoundUnaryMethod<C, M>(_unaryMethod);
4837 }
4838
optUsage(std::ostream & os,std::size_t indent=0,std::size_t width=Detail::consoleWidth) const4839 void optUsage(std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth) const
4840 {
4841 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4842 std::size_t maxWidth = 0;
4843 for (it = itBegin; it != itEnd; ++it)
4844 maxWidth = (std::max)(maxWidth, it->commands().size());
4845
4846 for (it = itBegin; it != itEnd; ++it)
4847 {
4848 Detail::Text usageText(it->commands(), Detail::TextAttributes()
4849 .setWidth(maxWidth + indent)
4850 .setIndent(indent));
4851 Detail::Text desc(it->description, Detail::TextAttributes()
4852 .setWidth(width - maxWidth - 3));
4853
4854 for (std::size_t i = 0; i < (std::max)(usageText.size(), desc.size()); ++i)
4855 {
4856 std::string usageCol = i < usageText.size() ? usageText[i] : "";
4857 os << usageCol;
4858
4859 if (i < desc.size() && !desc[i].empty())
4860 os << std::string(indent + 2 + maxWidth - usageCol.size(), ' ')
4861 << desc[i];
4862 os << "\n";
4863 }
4864 }
4865 }
optUsage() const4866 std::string optUsage() const
4867 {
4868 std::ostringstream oss;
4869 optUsage(oss);
4870 return oss.str();
4871 }
4872
argSynopsis(std::ostream & os) const4873 void argSynopsis(std::ostream& os) const
4874 {
4875 for (int i = 1; i <= m_highestSpecifiedArgPosition; ++i)
4876 {
4877 if (i > 1)
4878 os << " ";
4879 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find(i);
4880 if (it != m_positionalArgs.end())
4881 os << "<" << it->second.placeholder << ">";
4882 else if (m_floatingArg.get())
4883 os << "<" << m_floatingArg->placeholder << ">";
4884 else
4885 throw std::logic_error("non consecutive positional arguments with no floating args");
4886 }
4887 // !TBD No indication of mandatory args
4888 if (m_floatingArg.get())
4889 {
4890 if (m_highestSpecifiedArgPosition > 1)
4891 os << " ";
4892 os << "[<" << m_floatingArg->placeholder << "> ...]";
4893 }
4894 }
argSynopsis() const4895 std::string argSynopsis() const
4896 {
4897 std::ostringstream oss;
4898 argSynopsis(oss);
4899 return oss.str();
4900 }
4901
usage(std::ostream & os,std::string const & procName) const4902 void usage(std::ostream& os, std::string const& procName) const
4903 {
4904 validate();
4905 os << "usage:\n " << procName << " ";
4906 argSynopsis(os);
4907 if (!m_options.empty())
4908 {
4909 os << " [options]\n\nwhere options are: \n";
4910 optUsage(os, 2);
4911 }
4912 os << "\n";
4913 }
usage(std::string const & procName) const4914 std::string usage(std::string const& procName) const
4915 {
4916 std::ostringstream oss;
4917 usage(oss, procName);
4918 return oss.str();
4919 }
4920
parse(int argc,char const * const * argv) const4921 ConfigT parse(int argc, char const* const* argv) const
4922 {
4923 ConfigT config;
4924 parseInto(argc, argv, config);
4925 return config;
4926 }
4927
parseInto(int argc,char const * const * argv,ConfigT & config) const4928 std::vector<Parser::Token> parseInto(int argc, char const* const* argv, ConfigT& config) const
4929 {
4930 std::string processName = argv[0];
4931 std::size_t lastSlash = processName.find_last_of("/\\");
4932 if (lastSlash != std::string::npos)
4933 processName = processName.substr(lastSlash + 1);
4934 m_boundProcessName.set(config, processName);
4935 std::vector<Parser::Token> tokens;
4936 Parser parser;
4937 parser.parseIntoTokens(argc, argv, tokens);
4938 return populate(tokens, config);
4939 }
4940
populate(std::vector<Parser::Token> const & tokens,ConfigT & config) const4941 std::vector<Parser::Token> populate(std::vector<Parser::Token> const& tokens, ConfigT& config) const
4942 {
4943 validate();
4944 std::vector<Parser::Token> unusedTokens = populateOptions(tokens, config);
4945 unusedTokens = populateFixedArgs(unusedTokens, config);
4946 unusedTokens = populateFloatingArgs(unusedTokens, config);
4947 return unusedTokens;
4948 }
4949
populateOptions(std::vector<Parser::Token> const & tokens,ConfigT & config) const4950 std::vector<Parser::Token> populateOptions(std::vector<Parser::Token> const& tokens, ConfigT& config) const
4951 {
4952 std::vector<Parser::Token> unusedTokens;
4953 std::vector<std::string> errors;
4954 for (std::size_t i = 0; i < tokens.size(); ++i)
4955 {
4956 Parser::Token const& token = tokens[i];
4957 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4958 for (; it != itEnd; ++it)
4959 {
4960 Arg const& arg = *it;
4961
4962 try
4963 {
4964 if ((token.type == Parser::Token::ShortOpt && arg.hasShortName(token.data)) ||
4965 (token.type == Parser::Token::LongOpt && arg.hasLongName(token.data)))
4966 {
4967 if (arg.takesArg())
4968 {
4969 if (i == tokens.size() - 1 || tokens[i + 1].type != Parser::Token::Positional)
4970 errors.push_back("Expected argument to option: " + token.data);
4971 else
4972 arg.boundField.set(config, tokens[++i].data);
4973 }
4974 else
4975 {
4976 arg.boundField.setFlag(config);
4977 }
4978 break;
4979 }
4980 }
4981 catch (std::exception& ex)
4982 {
4983 errors.push_back(std::string(ex.what()) + "\n- while parsing: (" + arg.commands() + ")");
4984 }
4985 }
4986 if (it == itEnd)
4987 {
4988 if (token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens)
4989 unusedTokens.push_back(token);
4990 else if (errors.empty() && m_throwOnUnrecognisedTokens)
4991 errors.push_back("unrecognised option: " + token.data);
4992 }
4993 }
4994 if (!errors.empty())
4995 {
4996 std::ostringstream oss;
4997 for (std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
4998 it != itEnd;
4999 ++it)
5000 {
5001 if (it != errors.begin())
5002 oss << "\n";
5003 oss << *it;
5004 }
5005 throw std::runtime_error(oss.str());
5006 }
5007 return unusedTokens;
5008 }
populateFixedArgs(std::vector<Parser::Token> const & tokens,ConfigT & config) const5009 std::vector<Parser::Token> populateFixedArgs(std::vector<Parser::Token> const& tokens, ConfigT& config) const
5010 {
5011 std::vector<Parser::Token> unusedTokens;
5012 int position = 1;
5013 for (std::size_t i = 0; i < tokens.size(); ++i)
5014 {
5015 Parser::Token const& token = tokens[i];
5016 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find(position);
5017 if (it != m_positionalArgs.end())
5018 it->second.boundField.set(config, token.data);
5019 else
5020 unusedTokens.push_back(token);
5021 if (token.type == Parser::Token::Positional)
5022 position++;
5023 }
5024 return unusedTokens;
5025 }
populateFloatingArgs(std::vector<Parser::Token> const & tokens,ConfigT & config) const5026 std::vector<Parser::Token> populateFloatingArgs(std::vector<Parser::Token> const& tokens, ConfigT& config) const
5027 {
5028 if (!m_floatingArg.get())
5029 return tokens;
5030 std::vector<Parser::Token> unusedTokens;
5031 for (std::size_t i = 0; i < tokens.size(); ++i)
5032 {
5033 Parser::Token const& token = tokens[i];
5034 if (token.type == Parser::Token::Positional)
5035 m_floatingArg->boundField.set(config, token.data);
5036 else
5037 unusedTokens.push_back(token);
5038 }
5039 return unusedTokens;
5040 }
5041
validate() const5042 void validate() const
5043 {
5044 if (m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get())
5045 throw std::logic_error("No options or arguments specified");
5046
5047 for (typename std::vector<Arg>::const_iterator it = m_options.begin(),
5048 itEnd = m_options.end();
5049 it != itEnd; ++it)
5050 it->validate();
5051 }
5052
5053 private:
5054 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
5055 std::vector<Arg> m_options;
5056 std::map<int, Arg> m_positionalArgs;
5057 ArgAutoPtr m_floatingArg;
5058 int m_highestSpecifiedArgPosition;
5059 bool m_throwOnUnrecognisedTokens;
5060 };
5061
5062 } // end namespace Clara
5063
5064 STITCH_CLARA_CLOSE_NAMESPACE
5065 #undef STITCH_CLARA_OPEN_NAMESPACE
5066 #undef STITCH_CLARA_CLOSE_NAMESPACE
5067
5068 #endif // TWOBLUECUBES_CLARA_H_INCLUDED
5069 #undef STITCH_CLARA_OPEN_NAMESPACE
5070
5071 // Restore Clara's value for console width, if present
5072 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5073 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5074 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5075 #endif
5076
5077 #include <fstream>
5078
5079 namespace Catch {
5080
abortAfterFirst(ConfigData & config)5081 inline void abortAfterFirst(ConfigData& config) { config.abortAfter = 1; }
abortAfterX(ConfigData & config,int x)5082 inline void abortAfterX(ConfigData& config, int x)
5083 {
5084 if (x < 1)
5085 throw std::runtime_error("Value after -x or --abortAfter must be greater than zero");
5086 config.abortAfter = x;
5087 }
addTestOrTags(ConfigData & config,std::string const & _testSpec)5088 inline void addTestOrTags(ConfigData& config, std::string const& _testSpec) { config.testsOrTags.push_back(_testSpec); }
addReporterName(ConfigData & config,std::string const & _reporterName)5089 inline void addReporterName(ConfigData& config, std::string const& _reporterName) { config.reporterNames.push_back(_reporterName); }
5090
addWarning(ConfigData & config,std::string const & _warning)5091 inline void addWarning(ConfigData& config, std::string const& _warning)
5092 {
5093 if (_warning == "NoAssertions")
5094 config.warnings = static_cast<WarnAbout::What>(config.warnings | WarnAbout::NoAssertions);
5095 else
5096 throw std::runtime_error("Unrecognised warning: '" + _warning + "'");
5097 }
setOrder(ConfigData & config,std::string const & order)5098 inline void setOrder(ConfigData& config, std::string const& order)
5099 {
5100 if (startsWith("declared", order))
5101 config.runOrder = RunTests::InDeclarationOrder;
5102 else if (startsWith("lexical", order))
5103 config.runOrder = RunTests::InLexicographicalOrder;
5104 else if (startsWith("random", order))
5105 config.runOrder = RunTests::InRandomOrder;
5106 else
5107 throw std::runtime_error("Unrecognised ordering: '" + order + "'");
5108 }
setRngSeed(ConfigData & config,std::string const & seed)5109 inline void setRngSeed(ConfigData& config, std::string const& seed)
5110 {
5111 if (seed == "time")
5112 {
5113 config.rngSeed = static_cast<unsigned int>(std::time(0));
5114 }
5115 else
5116 {
5117 std::stringstream ss;
5118 ss << seed;
5119 ss >> config.rngSeed;
5120 if (ss.fail())
5121 throw std::runtime_error("Argment to --rng-seed should be the word 'time' or a number");
5122 }
5123 }
setVerbosity(ConfigData & config,int level)5124 inline void setVerbosity(ConfigData& config, int level)
5125 {
5126 // !TBD: accept strings?
5127 config.verbosity = static_cast<Verbosity::Level>(level);
5128 }
setShowDurations(ConfigData & config,bool _showDurations)5129 inline void setShowDurations(ConfigData& config, bool _showDurations)
5130 {
5131 config.showDurations = _showDurations
5132 ? ShowDurations::Always
5133 : ShowDurations::Never;
5134 }
loadTestNamesFromFile(ConfigData & config,std::string const & _filename)5135 inline void loadTestNamesFromFile(ConfigData& config, std::string const& _filename)
5136 {
5137 std::ifstream f(_filename.c_str());
5138 if (!f.is_open())
5139 throw std::domain_error("Unable to load input file: " + _filename);
5140
5141 std::string line;
5142 while (std::getline(f, line))
5143 {
5144 line = trim(line);
5145 if (!line.empty() && !startsWith(line, "#"))
5146 addTestOrTags(config, "\"" + line + "\",");
5147 }
5148 }
5149
makeCommandLineParser()5150 inline Clara::CommandLine<ConfigData> makeCommandLineParser()
5151 {
5152
5153 using namespace Clara;
5154 CommandLine<ConfigData> cli;
5155
5156 cli.bindProcessName(&ConfigData::processName);
5157
5158 cli["-?"]["-h"]["--help"]
5159 .describe("display usage information")
5160 .bind(&ConfigData::showHelp);
5161
5162 cli["-l"]["--list-tests"]
5163 .describe("list all/matching test cases")
5164 .bind(&ConfigData::listTests);
5165
5166 cli["-t"]["--list-tags"]
5167 .describe("list all/matching tags")
5168 .bind(&ConfigData::listTags);
5169
5170 cli["-s"]["--success"]
5171 .describe("include successful tests in output")
5172 .bind(&ConfigData::showSuccessfulTests);
5173
5174 cli["-b"]["--break"]
5175 .describe("break into debugger on failure")
5176 .bind(&ConfigData::shouldDebugBreak);
5177
5178 cli["-e"]["--nothrow"]
5179 .describe("skip exception tests")
5180 .bind(&ConfigData::noThrow);
5181
5182 cli["-i"]["--invisibles"]
5183 .describe("show invisibles (tabs, newlines)")
5184 .bind(&ConfigData::showInvisibles);
5185
5186 cli["-o"]["--out"]
5187 .describe("output filename")
5188 .bind(&ConfigData::outputFilename, "filename");
5189
5190 cli["-r"]["--reporter"]
5191 // .placeholder( "name[:filename]" )
5192 .describe("reporter to use (defaults to console)")
5193 .bind(&addReporterName, "name");
5194
5195 cli["-n"]["--name"]
5196 .describe("suite name")
5197 .bind(&ConfigData::name, "name");
5198
5199 cli["-a"]["--abort"]
5200 .describe("abort at first failure")
5201 .bind(&abortAfterFirst);
5202
5203 cli["-x"]["--abortx"]
5204 .describe("abort after x failures")
5205 .bind(&abortAfterX, "no. failures");
5206
5207 cli["-w"]["--warn"]
5208 .describe("enable warnings")
5209 .bind(&addWarning, "warning name");
5210
5211 // - needs updating if reinstated
5212 // cli.into( &setVerbosity )
5213 // .describe( "level of verbosity (0=no output)" )
5214 // .shortOpt( "v")
5215 // .longOpt( "verbosity" )
5216 // .placeholder( "level" );
5217
5218 cli[_]
5219 .describe("which test or tests to use")
5220 .bind(&addTestOrTags, "test name, pattern or tags");
5221
5222 cli["-d"]["--durations"]
5223 .describe("show test durations")
5224 .bind(&setShowDurations, "yes/no");
5225
5226 cli["-f"]["--input-file"]
5227 .describe("load test names to run from a file")
5228 .bind(&loadTestNamesFromFile, "filename");
5229
5230 cli["-#"]["--filenames-as-tags"]
5231 .describe("adds a tag for the filename")
5232 .bind(&ConfigData::filenamesAsTags);
5233
5234 // Less common commands which don't have a short form
5235 cli["--list-test-names-only"]
5236 .describe("list all/matching test cases names only")
5237 .bind(&ConfigData::listTestNamesOnly);
5238
5239 cli["--list-reporters"]
5240 .describe("list all reporters")
5241 .bind(&ConfigData::listReporters);
5242
5243 cli["--order"]
5244 .describe("test case order (defaults to decl)")
5245 .bind(&setOrder, "decl|lex|rand");
5246
5247 cli["--rng-seed"]
5248 .describe("set a specific seed for random numbers")
5249 .bind(&setRngSeed, "'time'|number");
5250
5251 cli["--force-colour"]
5252 .describe("force colourised output")
5253 .bind(&ConfigData::forceColour);
5254
5255 return cli;
5256 }
5257
5258 } // end namespace Catch
5259
5260 // #included from: internal/catch_list.hpp
5261 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
5262
5263 // #included from: catch_text.h
5264 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
5265
5266 #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
5267
5268 #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
5269 // #included from: ../external/tbc_text_format.h
5270 // Only use header guard if we are not using an outer namespace
5271 #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5272 #ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5273 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5274 #define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5275 #endif
5276 #else
5277 #define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5278 #endif
5279 #endif
5280 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5281 #include <sstream>
5282 #include <string>
5283 #include <vector>
5284
5285 // Use optional outer namespace
5286 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5287 namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
5288 #endif
5289
5290 namespace Tbc {
5291
5292 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
5293 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
5294 #else
5295 const unsigned int consoleWidth = 80;
5296 #endif
5297
5298 struct TextAttributes
5299 {
TextAttributesCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes5300 TextAttributes()
5301 : initialIndent(std::string::npos),
5302 indent(0),
5303 width(consoleWidth - 1),
5304 tabChar('\t')
5305 {
5306 }
5307
setInitialIndentCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes5308 TextAttributes& setInitialIndent(std::size_t _value)
5309 {
5310 initialIndent = _value;
5311 return *this;
5312 }
setIndentCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes5313 TextAttributes& setIndent(std::size_t _value)
5314 {
5315 indent = _value;
5316 return *this;
5317 }
setWidthCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes5318 TextAttributes& setWidth(std::size_t _value)
5319 {
5320 width = _value;
5321 return *this;
5322 }
setTabCharCLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE::Tbc::TextAttributes5323 TextAttributes& setTabChar(char _value)
5324 {
5325 tabChar = _value;
5326 return *this;
5327 }
5328
5329 std::size_t initialIndent; // indent of first line, or npos
5330 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
5331 std::size_t width; // maximum width of text, including indent. Longer text will wrap
5332 char tabChar; // If this char is seen the indent is changed to current pos
5333 };
5334
5335 class Text
5336 {
5337 public:
Text(std::string const & _str,TextAttributes const & _attr=TextAttributes ())5338 Text(std::string const& _str, TextAttributes const& _attr = TextAttributes())
5339 : attr(_attr)
5340 {
5341 std::string wrappableChars = " [({.,/|\\-";
5342 std::size_t indent = _attr.initialIndent != std::string::npos
5343 ? _attr.initialIndent
5344 : _attr.indent;
5345 std::string remainder = _str;
5346
5347 while (!remainder.empty())
5348 {
5349 if (lines.size() >= 1000)
5350 {
5351 lines.push_back("... message truncated due to excessive size");
5352 return;
5353 }
5354 std::size_t tabPos = std::string::npos;
5355 std::size_t width = (std::min)(remainder.size(), _attr.width - indent);
5356 std::size_t pos = remainder.find_first_of('\n');
5357 if (pos <= width)
5358 {
5359 width = pos;
5360 }
5361 pos = remainder.find_last_of(_attr.tabChar, width);
5362 if (pos != std::string::npos)
5363 {
5364 tabPos = pos;
5365 if (remainder[width] == '\n')
5366 width--;
5367 remainder = remainder.substr(0, tabPos) + remainder.substr(tabPos + 1);
5368 }
5369
5370 if (width == remainder.size())
5371 {
5372 spliceLine(indent, remainder, width);
5373 }
5374 else if (remainder[width] == '\n')
5375 {
5376 spliceLine(indent, remainder, width);
5377 if (width <= 1 || remainder.size() != 1)
5378 remainder = remainder.substr(1);
5379 indent = _attr.indent;
5380 }
5381 else
5382 {
5383 pos = remainder.find_last_of(wrappableChars, width);
5384 if (pos != std::string::npos && pos > 0)
5385 {
5386 spliceLine(indent, remainder, pos);
5387 if (remainder[0] == ' ')
5388 remainder = remainder.substr(1);
5389 }
5390 else
5391 {
5392 spliceLine(indent, remainder, width - 1);
5393 lines.back() += "-";
5394 }
5395 if (lines.size() == 1)
5396 indent = _attr.indent;
5397 if (tabPos != std::string::npos)
5398 indent += tabPos;
5399 }
5400 }
5401 }
5402
spliceLine(std::size_t _indent,std::string & _remainder,std::size_t _pos)5403 void spliceLine(std::size_t _indent, std::string& _remainder, std::size_t _pos)
5404 {
5405 lines.push_back(std::string(_indent, ' ') + _remainder.substr(0, _pos));
5406 _remainder = _remainder.substr(_pos);
5407 }
5408
5409 typedef std::vector<std::string>::const_iterator const_iterator;
5410
begin() const5411 const_iterator begin() const { return lines.begin(); }
end() const5412 const_iterator end() const { return lines.end(); }
last() const5413 std::string const& last() const { return lines.back(); }
size() const5414 std::size_t size() const { return lines.size(); }
operator [](std::size_t _index) const5415 std::string const& operator[](std::size_t _index) const { return lines[_index]; }
toString() const5416 std::string toString() const
5417 {
5418 std::ostringstream oss;
5419 oss << *this;
5420 return oss.str();
5421 }
5422
operator <<(std::ostream & _stream,Text const & _text)5423 inline friend std::ostream& operator<<(std::ostream& _stream, Text const& _text)
5424 {
5425 for (Text::const_iterator it = _text.begin(), itEnd = _text.end();
5426 it != itEnd; ++it)
5427 {
5428 if (it != _text.begin())
5429 _stream << "\n";
5430 _stream << *it;
5431 }
5432 return _stream;
5433 }
5434
5435 private:
5436 std::string str;
5437 TextAttributes attr;
5438 std::vector<std::string> lines;
5439 };
5440
5441 } // end namespace Tbc
5442
5443 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5444 } // end outer namespace
5445 #endif
5446
5447 #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5448 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5449
5450 namespace Catch {
5451 using Tbc::Text;
5452 using Tbc::TextAttributes;
5453 }
5454
5455 // #included from: catch_console_colour.hpp
5456 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
5457
5458 namespace Catch {
5459
5460 struct Colour
5461 {
5462 enum Code
5463 {
5464 None = 0,
5465
5466 White,
5467 Red,
5468 Green,
5469 Blue,
5470 Cyan,
5471 Yellow,
5472 Grey,
5473
5474 Bright = 0x10,
5475
5476 BrightRed = Bright | Red,
5477 BrightGreen = Bright | Green,
5478 LightGrey = Bright | Grey,
5479 BrightWhite = Bright | White,
5480
5481 // By intention
5482 FileName = LightGrey,
5483 Warning = Yellow,
5484 ResultError = BrightRed,
5485 ResultSuccess = BrightGreen,
5486 ResultExpectedFailure = Warning,
5487
5488 Error = BrightRed,
5489 Success = Green,
5490
5491 OriginalExpression = Cyan,
5492 ReconstructedExpression = Yellow,
5493
5494 SecondaryText = LightGrey,
5495 Headers = White
5496 };
5497
5498 // Use constructed object for RAII guard
5499 Colour(Code _colourCode);
5500 Colour(Colour const& other);
5501 ~Colour();
5502
5503 // Use static method for one-shot changes
5504 static void use(Code _colourCode);
5505
5506 private:
5507 bool m_moved;
5508 };
5509
operator <<(std::ostream & os,Colour const &)5510 inline std::ostream& operator<<(std::ostream& os, Colour const&) { return os; }
5511
5512 } // end namespace Catch
5513
5514 // #included from: catch_interfaces_reporter.h
5515 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
5516
5517 #include <assert.h>
5518 #include <map>
5519 #include <ostream>
5520 #include <string>
5521
5522 namespace Catch {
5523 struct ReporterConfig
5524 {
ReporterConfigCatch::ReporterConfig5525 explicit ReporterConfig(Ptr<IConfig const> const& _fullConfig)
5526 : m_stream(&_fullConfig->stream()), m_fullConfig(_fullConfig) {}
5527
ReporterConfigCatch::ReporterConfig5528 ReporterConfig(Ptr<IConfig const> const& _fullConfig, std::ostream& _stream)
5529 : m_stream(&_stream), m_fullConfig(_fullConfig) {}
5530
streamCatch::ReporterConfig5531 std::ostream& stream() const { return *m_stream; }
fullConfigCatch::ReporterConfig5532 Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
5533
5534 private:
5535 std::ostream* m_stream;
5536 Ptr<IConfig const> m_fullConfig;
5537 };
5538
5539 struct ReporterPreferences
5540 {
ReporterPreferencesCatch::ReporterPreferences5541 ReporterPreferences()
5542 : shouldRedirectStdOut(false)
5543 {
5544 }
5545
5546 bool shouldRedirectStdOut;
5547 };
5548
5549 template <typename T>
5550 struct LazyStat : Option<T>
5551 {
LazyStatCatch::LazyStat5552 LazyStat() : used(false) {}
operator =Catch::LazyStat5553 LazyStat& operator=(T const& _value)
5554 {
5555 Option<T>::operator=(_value);
5556 used = false;
5557 return *this;
5558 }
resetCatch::LazyStat5559 void reset()
5560 {
5561 Option<T>::reset();
5562 used = false;
5563 }
5564 bool used;
5565 };
5566
5567 struct TestRunInfo
5568 {
TestRunInfoCatch::TestRunInfo5569 TestRunInfo(std::string const& _name) : name(_name) {}
5570 std::string name;
5571 };
5572 struct GroupInfo
5573 {
GroupInfoCatch::GroupInfo5574 GroupInfo(std::string const& _name,
5575 std::size_t _groupIndex,
5576 std::size_t _groupsCount)
5577 : name(_name),
5578 groupIndex(_groupIndex),
5579 groupsCounts(_groupsCount)
5580 {
5581 }
5582
5583 std::string name;
5584 std::size_t groupIndex;
5585 std::size_t groupsCounts;
5586 };
5587
5588 struct AssertionStats
5589 {
AssertionStatsCatch::AssertionStats5590 AssertionStats(AssertionResult const& _assertionResult,
5591 std::vector<MessageInfo> const& _infoMessages,
5592 Totals const& _totals)
5593 : assertionResult(_assertionResult),
5594 infoMessages(_infoMessages),
5595 totals(_totals)
5596 {
5597 if (assertionResult.hasMessage())
5598 {
5599 // Copy message into messages list.
5600 // !TBD This should have been done earlier, somewhere
5601 MessageBuilder builder(assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType());
5602 builder << assertionResult.getMessage();
5603 builder.m_info.message = builder.m_stream.str();
5604
5605 infoMessages.push_back(builder.m_info);
5606 }
5607 }
5608 virtual ~AssertionStats();
5609
5610 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5611 AssertionStats(AssertionStats const&) = default;
5612 AssertionStats(AssertionStats&&) = default;
5613 AssertionStats& operator=(AssertionStats const&) = default;
5614 AssertionStats& operator=(AssertionStats&&) = default;
5615 #endif
5616
5617 AssertionResult assertionResult;
5618 std::vector<MessageInfo> infoMessages;
5619 Totals totals;
5620 };
5621
5622 struct SectionStats
5623 {
SectionStatsCatch::SectionStats5624 SectionStats(SectionInfo const& _sectionInfo,
5625 Counts const& _assertions,
5626 double _durationInSeconds,
5627 bool _missingAssertions)
5628 : sectionInfo(_sectionInfo),
5629 assertions(_assertions),
5630 durationInSeconds(_durationInSeconds),
5631 missingAssertions(_missingAssertions)
5632 {
5633 }
5634 virtual ~SectionStats();
5635 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5636 SectionStats(SectionStats const&) = default;
5637 SectionStats(SectionStats&&) = default;
5638 SectionStats& operator=(SectionStats const&) = default;
5639 SectionStats& operator=(SectionStats&&) = default;
5640 #endif
5641
5642 SectionInfo sectionInfo;
5643 Counts assertions;
5644 double durationInSeconds;
5645 bool missingAssertions;
5646 };
5647
5648 struct TestCaseStats
5649 {
TestCaseStatsCatch::TestCaseStats5650 TestCaseStats(TestCaseInfo const& _testInfo,
5651 Totals const& _totals,
5652 std::string const& _stdOut,
5653 std::string const& _stdErr,
5654 bool _aborting)
5655 : testInfo(_testInfo),
5656 totals(_totals),
5657 stdOut(_stdOut),
5658 stdErr(_stdErr),
5659 aborting(_aborting)
5660 {
5661 }
5662 virtual ~TestCaseStats();
5663
5664 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5665 TestCaseStats(TestCaseStats const&) = default;
5666 TestCaseStats(TestCaseStats&&) = default;
5667 TestCaseStats& operator=(TestCaseStats const&) = default;
5668 TestCaseStats& operator=(TestCaseStats&&) = default;
5669 #endif
5670
5671 TestCaseInfo testInfo;
5672 Totals totals;
5673 std::string stdOut;
5674 std::string stdErr;
5675 bool aborting;
5676 };
5677
5678 struct TestGroupStats
5679 {
TestGroupStatsCatch::TestGroupStats5680 TestGroupStats(GroupInfo const& _groupInfo,
5681 Totals const& _totals,
5682 bool _aborting)
5683 : groupInfo(_groupInfo),
5684 totals(_totals),
5685 aborting(_aborting)
5686 {
5687 }
TestGroupStatsCatch::TestGroupStats5688 TestGroupStats(GroupInfo const& _groupInfo)
5689 : groupInfo(_groupInfo),
5690 aborting(false)
5691 {
5692 }
5693 virtual ~TestGroupStats();
5694
5695 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5696 TestGroupStats(TestGroupStats const&) = default;
5697 TestGroupStats(TestGroupStats&&) = default;
5698 TestGroupStats& operator=(TestGroupStats const&) = default;
5699 TestGroupStats& operator=(TestGroupStats&&) = default;
5700 #endif
5701
5702 GroupInfo groupInfo;
5703 Totals totals;
5704 bool aborting;
5705 };
5706
5707 struct TestRunStats
5708 {
TestRunStatsCatch::TestRunStats5709 TestRunStats(TestRunInfo const& _runInfo,
5710 Totals const& _totals,
5711 bool _aborting)
5712 : runInfo(_runInfo),
5713 totals(_totals),
5714 aborting(_aborting)
5715 {
5716 }
5717 virtual ~TestRunStats();
5718
5719 #ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestRunStatsCatch::TestRunStats5720 TestRunStats(TestRunStats const& _other)
5721 : runInfo(_other.runInfo),
5722 totals(_other.totals),
5723 aborting(_other.aborting)
5724 {
5725 }
5726 #else
5727 TestRunStats(TestRunStats const&) = default;
5728 TestRunStats(TestRunStats&&) = default;
5729 TestRunStats& operator=(TestRunStats const&) = default;
5730 TestRunStats& operator=(TestRunStats&&) = default;
5731 #endif
5732
5733 TestRunInfo runInfo;
5734 Totals totals;
5735 bool aborting;
5736 };
5737
5738 struct IStreamingReporter : IShared
5739 {
5740 virtual ~IStreamingReporter();
5741
5742 // Implementing class must also provide the following static method:
5743 // static std::string getDescription();
5744
5745 virtual ReporterPreferences getPreferences() const = 0;
5746
5747 virtual void noMatchingTestCases(std::string const& spec) = 0;
5748
5749 virtual void testRunStarting(TestRunInfo const& testRunInfo) = 0;
5750 virtual void testGroupStarting(GroupInfo const& groupInfo) = 0;
5751
5752 virtual void testCaseStarting(TestCaseInfo const& testInfo) = 0;
5753 virtual void sectionStarting(SectionInfo const& sectionInfo) = 0;
5754
5755 virtual void assertionStarting(AssertionInfo const& assertionInfo) = 0;
5756
5757 // The return value indicates if the messages buffer should be cleared:
5758 virtual bool assertionEnded(AssertionStats const& assertionStats) = 0;
5759
5760 virtual void sectionEnded(SectionStats const& sectionStats) = 0;
5761 virtual void testCaseEnded(TestCaseStats const& testCaseStats) = 0;
5762 virtual void testGroupEnded(TestGroupStats const& testGroupStats) = 0;
5763 virtual void testRunEnded(TestRunStats const& testRunStats) = 0;
5764
5765 virtual void skipTest(TestCaseInfo const& testInfo) = 0;
5766 };
5767
5768 struct IReporterFactory : IShared
5769 {
5770 virtual ~IReporterFactory();
5771 virtual IStreamingReporter* create(ReporterConfig const& config) const = 0;
5772 virtual std::string getDescription() const = 0;
5773 };
5774
5775 struct IReporterRegistry
5776 {
5777 typedef std::map<std::string, Ptr<IReporterFactory>> FactoryMap;
5778 typedef std::vector<Ptr<IReporterFactory>> Listeners;
5779
5780 virtual ~IReporterRegistry();
5781 virtual IStreamingReporter* create(std::string const& name, Ptr<IConfig const> const& config) const = 0;
5782 virtual FactoryMap const& getFactories() const = 0;
5783 virtual Listeners const& getListeners() const = 0;
5784 };
5785
5786 Ptr<IStreamingReporter> addReporter(Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter);
5787 }
5788
5789 #include <algorithm>
5790 #include <limits>
5791
5792 namespace Catch {
5793
listTests(Config const & config)5794 inline std::size_t listTests(Config const& config)
5795 {
5796
5797 TestSpec testSpec = config.testSpec();
5798 if (config.testSpec().hasFilters())
5799 Catch::cout() << "Matching test cases:\n";
5800 else
5801 {
5802 Catch::cout() << "All available test cases:\n";
5803 testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("*").testSpec();
5804 }
5805
5806 std::size_t matchedTests = 0;
5807 TextAttributes nameAttr, tagsAttr;
5808 nameAttr.setInitialIndent(2).setIndent(4);
5809 tagsAttr.setIndent(6);
5810
5811 std::vector<TestCase> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
5812 for (std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5813 it != itEnd;
5814 ++it)
5815 {
5816 matchedTests++;
5817 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5818 Colour::Code colour = testCaseInfo.isHidden()
5819 ? Colour::SecondaryText
5820 : Colour::None;
5821 Colour colourGuard(colour);
5822
5823 Catch::cout() << Text(testCaseInfo.name, nameAttr) << std::endl;
5824 if (!testCaseInfo.tags.empty())
5825 Catch::cout() << Text(testCaseInfo.tagsAsString, tagsAttr) << std::endl;
5826 }
5827
5828 if (!config.testSpec().hasFilters())
5829 Catch::cout() << pluralise(matchedTests, "test case") << "\n"
5830 << std::endl;
5831 else
5832 Catch::cout() << pluralise(matchedTests, "matching test case") << "\n"
5833 << std::endl;
5834 return matchedTests;
5835 }
5836
listTestsNamesOnly(Config const & config)5837 inline std::size_t listTestsNamesOnly(Config const& config)
5838 {
5839 TestSpec testSpec = config.testSpec();
5840 if (!config.testSpec().hasFilters())
5841 testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("*").testSpec();
5842 std::size_t matchedTests = 0;
5843 std::vector<TestCase> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
5844 for (std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5845 it != itEnd;
5846 ++it)
5847 {
5848 matchedTests++;
5849 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5850 Catch::cout() << testCaseInfo.name << std::endl;
5851 }
5852 return matchedTests;
5853 }
5854
5855 struct TagInfo
5856 {
TagInfoCatch::TagInfo5857 TagInfo() : count(0) {}
addCatch::TagInfo5858 void add(std::string const& spelling)
5859 {
5860 ++count;
5861 spellings.insert(spelling);
5862 }
allCatch::TagInfo5863 std::string all() const
5864 {
5865 std::string out;
5866 for (std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5867 it != itEnd;
5868 ++it)
5869 out += "[" + *it + "]";
5870 return out;
5871 }
5872 std::set<std::string> spellings;
5873 std::size_t count;
5874 };
5875
listTags(Config const & config)5876 inline std::size_t listTags(Config const& config)
5877 {
5878 TestSpec testSpec = config.testSpec();
5879 if (config.testSpec().hasFilters())
5880 Catch::cout() << "Tags for matching test cases:\n";
5881 else
5882 {
5883 Catch::cout() << "All available tags:\n";
5884 testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("*").testSpec();
5885 }
5886
5887 std::map<std::string, TagInfo> tagCounts;
5888
5889 std::vector<TestCase> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
5890 for (std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5891 it != itEnd;
5892 ++it)
5893 {
5894 for (std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5895 tagItEnd = it->getTestCaseInfo().tags.end();
5896 tagIt != tagItEnd;
5897 ++tagIt)
5898 {
5899 std::string tagName = *tagIt;
5900 std::string lcaseTagName = toLower(tagName);
5901 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find(lcaseTagName);
5902 if (countIt == tagCounts.end())
5903 countIt = tagCounts.insert(std::make_pair(lcaseTagName, TagInfo())).first;
5904 countIt->second.add(tagName);
5905 }
5906 }
5907
5908 for (std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5909 countItEnd = tagCounts.end();
5910 countIt != countItEnd;
5911 ++countIt)
5912 {
5913 std::ostringstream oss;
5914 oss << " " << std::setw(2) << countIt->second.count << " ";
5915 Text wrapper(countIt->second.all(), TextAttributes()
5916 .setInitialIndent(0)
5917 .setIndent(oss.str().size())
5918 .setWidth(CATCH_CONFIG_CONSOLE_WIDTH - 10));
5919 Catch::cout() << oss.str() << wrapper << "\n";
5920 }
5921 Catch::cout() << pluralise(tagCounts.size(), "tag") << "\n"
5922 << std::endl;
5923 return tagCounts.size();
5924 }
5925
listReporters(Config const &)5926 inline std::size_t listReporters(Config const& /*config*/)
5927 {
5928 Catch::cout() << "Available reporters:\n";
5929 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
5930 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
5931 std::size_t maxNameLen = 0;
5932 for (it = itBegin; it != itEnd; ++it)
5933 maxNameLen = (std::max)(maxNameLen, it->first.size());
5934
5935 for (it = itBegin; it != itEnd; ++it)
5936 {
5937 Text wrapper(it->second->getDescription(), TextAttributes()
5938 .setInitialIndent(0)
5939 .setIndent(7 + maxNameLen)
5940 .setWidth(CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8));
5941 Catch::cout() << " "
5942 << it->first
5943 << ":"
5944 << std::string(maxNameLen - it->first.size() + 2, ' ')
5945 << wrapper << "\n";
5946 }
5947 Catch::cout() << std::endl;
5948 return factories.size();
5949 }
5950
list(Config const & config)5951 inline Option<std::size_t> list(Config const& config)
5952 {
5953 Option<std::size_t> listedCount;
5954 if (config.listTests())
5955 listedCount = listedCount.valueOr(0) + listTests(config);
5956 if (config.listTestNamesOnly())
5957 listedCount = listedCount.valueOr(0) + listTestsNamesOnly(config);
5958 if (config.listTags())
5959 listedCount = listedCount.valueOr(0) + listTags(config);
5960 if (config.listReporters())
5961 listedCount = listedCount.valueOr(0) + listReporters(config);
5962 return listedCount;
5963 }
5964
5965 } // end namespace Catch
5966
5967 // #included from: internal/catch_run_context.hpp
5968 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
5969
5970 // #included from: catch_test_case_tracker.hpp
5971 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
5972
5973 #include <assert.h>
5974 #include <map>
5975 #include <string>
5976 #include <vector>
5977
5978 namespace Catch {
5979 namespace TestCaseTracking {
5980
5981 struct ITracker : SharedImpl<>
5982 {
5983 virtual ~ITracker();
5984
5985 // static queries
5986 virtual std::string name() const = 0;
5987
5988 // dynamic queries
5989 virtual bool isComplete() const = 0; // Successfully completed or failed
5990 virtual bool isSuccessfullyCompleted() const = 0;
5991 virtual bool isOpen() const = 0; // Started but not complete
5992 virtual bool hasChildren() const = 0;
5993
5994 virtual ITracker& parent() = 0;
5995
5996 // actions
5997 virtual void close() = 0; // Successfully complete
5998 virtual void fail() = 0;
5999 virtual void markAsNeedingAnotherRun() = 0;
6000
6001 virtual void addChild(Ptr<ITracker> const& child) = 0;
6002 virtual ITracker* findChild(std::string const& name) = 0;
6003 virtual void openChild() = 0;
6004 };
6005
6006 class TrackerContext
6007 {
6008
6009 enum RunState
6010 {
6011 NotStarted,
6012 Executing,
6013 CompletedCycle
6014 };
6015
6016 Ptr<ITracker> m_rootTracker;
6017 ITracker* m_currentTracker;
6018 RunState m_runState;
6019
6020 public:
instance()6021 static TrackerContext& instance()
6022 {
6023 static TrackerContext s_instance;
6024 return s_instance;
6025 }
6026
TrackerContext()6027 TrackerContext()
6028 : m_currentTracker(CATCH_NULL),
6029 m_runState(NotStarted)
6030 {
6031 }
6032
6033 ITracker& startRun();
6034
endRun()6035 void endRun()
6036 {
6037 m_rootTracker.reset();
6038 m_currentTracker = CATCH_NULL;
6039 m_runState = NotStarted;
6040 }
6041
startCycle()6042 void startCycle()
6043 {
6044 m_currentTracker = m_rootTracker.get();
6045 m_runState = Executing;
6046 }
completeCycle()6047 void completeCycle()
6048 {
6049 m_runState = CompletedCycle;
6050 }
6051
completedCycle() const6052 bool completedCycle() const
6053 {
6054 return m_runState == CompletedCycle;
6055 }
currentTracker()6056 ITracker& currentTracker()
6057 {
6058 return *m_currentTracker;
6059 }
setCurrentTracker(ITracker * tracker)6060 void setCurrentTracker(ITracker* tracker)
6061 {
6062 m_currentTracker = tracker;
6063 }
6064 };
6065
6066 class TrackerBase : public ITracker
6067 {
6068 protected:
6069 enum CycleState
6070 {
6071 NotStarted,
6072 Executing,
6073 ExecutingChildren,
6074 NeedsAnotherRun,
6075 CompletedSuccessfully,
6076 Failed
6077 };
6078 class TrackerHasName
6079 {
6080 std::string m_name;
6081
6082 public:
TrackerHasName(std::string const & name)6083 TrackerHasName(std::string const& name) : m_name(name) {}
operator ()(Ptr<ITracker> const & tracker)6084 bool operator()(Ptr<ITracker> const& tracker)
6085 {
6086 return tracker->name() == m_name;
6087 }
6088 };
6089 typedef std::vector<Ptr<ITracker>> Children;
6090 std::string m_name;
6091 TrackerContext& m_ctx;
6092 ITracker* m_parent;
6093 Children m_children;
6094 CycleState m_runState;
6095
6096 public:
TrackerBase(std::string const & name,TrackerContext & ctx,ITracker * parent)6097 TrackerBase(std::string const& name, TrackerContext& ctx, ITracker* parent)
6098 : m_name(name),
6099 m_ctx(ctx),
6100 m_parent(parent),
6101 m_runState(NotStarted)
6102 {
6103 }
6104 virtual ~TrackerBase();
6105
name() const6106 virtual std::string name() const CATCH_OVERRIDE
6107 {
6108 return m_name;
6109 }
isComplete() const6110 virtual bool isComplete() const CATCH_OVERRIDE
6111 {
6112 return m_runState == CompletedSuccessfully || m_runState == Failed;
6113 }
isSuccessfullyCompleted() const6114 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE
6115 {
6116 return m_runState == CompletedSuccessfully;
6117 }
isOpen() const6118 virtual bool isOpen() const CATCH_OVERRIDE
6119 {
6120 return m_runState != NotStarted && !isComplete();
6121 }
hasChildren() const6122 virtual bool hasChildren() const CATCH_OVERRIDE
6123 {
6124 return !m_children.empty();
6125 }
6126
addChild(Ptr<ITracker> const & child)6127 virtual void addChild(Ptr<ITracker> const& child) CATCH_OVERRIDE
6128 {
6129 m_children.push_back(child);
6130 }
6131
findChild(std::string const & name)6132 virtual ITracker* findChild(std::string const& name) CATCH_OVERRIDE
6133 {
6134 Children::const_iterator it = std::find_if(m_children.begin(), m_children.end(), TrackerHasName(name));
6135 return (it != m_children.end())
6136 ? it->get()
6137 : CATCH_NULL;
6138 }
parent()6139 virtual ITracker& parent() CATCH_OVERRIDE
6140 {
6141 assert(m_parent); // Should always be non-null except for root
6142 return *m_parent;
6143 }
6144
openChild()6145 virtual void openChild() CATCH_OVERRIDE
6146 {
6147 if (m_runState != ExecutingChildren)
6148 {
6149 m_runState = ExecutingChildren;
6150 if (m_parent)
6151 m_parent->openChild();
6152 }
6153 }
open()6154 void open()
6155 {
6156 m_runState = Executing;
6157 moveToThis();
6158 if (m_parent)
6159 m_parent->openChild();
6160 }
6161
close()6162 virtual void close() CATCH_OVERRIDE
6163 {
6164
6165 // Close any still open children (e.g. generators)
6166 while (&m_ctx.currentTracker() != this)
6167 m_ctx.currentTracker().close();
6168
6169 switch (m_runState)
6170 {
6171 case NotStarted:
6172 case CompletedSuccessfully:
6173 case Failed:
6174 throw std::logic_error("Illogical state");
6175
6176 case NeedsAnotherRun:
6177 break;
6178 ;
6179
6180 case Executing:
6181 m_runState = CompletedSuccessfully;
6182 break;
6183 case ExecutingChildren:
6184 if (m_children.empty() || m_children.back()->isComplete())
6185 m_runState = CompletedSuccessfully;
6186 break;
6187
6188 default:
6189 throw std::logic_error("Unexpected state");
6190 }
6191 moveToParent();
6192 m_ctx.completeCycle();
6193 }
fail()6194 virtual void fail() CATCH_OVERRIDE
6195 {
6196 m_runState = Failed;
6197 if (m_parent)
6198 m_parent->markAsNeedingAnotherRun();
6199 moveToParent();
6200 m_ctx.completeCycle();
6201 }
markAsNeedingAnotherRun()6202 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE
6203 {
6204 m_runState = NeedsAnotherRun;
6205 }
6206
6207 private:
moveToParent()6208 void moveToParent()
6209 {
6210 assert(m_parent);
6211 m_ctx.setCurrentTracker(m_parent);
6212 }
moveToThis()6213 void moveToThis()
6214 {
6215 m_ctx.setCurrentTracker(this);
6216 }
6217 };
6218
6219 class SectionTracker : public TrackerBase
6220 {
6221 public:
SectionTracker(std::string const & name,TrackerContext & ctx,ITracker * parent)6222 SectionTracker(std::string const& name, TrackerContext& ctx, ITracker* parent)
6223 : TrackerBase(name, ctx, parent)
6224 {
6225 }
6226 virtual ~SectionTracker();
6227
acquire(TrackerContext & ctx,std::string const & name)6228 static SectionTracker& acquire(TrackerContext& ctx, std::string const& name)
6229 {
6230 SectionTracker* section = CATCH_NULL;
6231
6232 ITracker& currentTracker = ctx.currentTracker();
6233 if (ITracker* childTracker = currentTracker.findChild(name))
6234 {
6235 section = dynamic_cast<SectionTracker*>(childTracker);
6236 assert(section);
6237 }
6238 else
6239 {
6240 section = new SectionTracker(name, ctx, ¤tTracker);
6241 currentTracker.addChild(section);
6242 }
6243 if (!ctx.completedCycle() && !section->isComplete())
6244 {
6245
6246 section->open();
6247 }
6248 return *section;
6249 }
6250 };
6251
6252 class IndexTracker : public TrackerBase
6253 {
6254 int m_size;
6255 int m_index;
6256
6257 public:
IndexTracker(std::string const & name,TrackerContext & ctx,ITracker * parent,int size)6258 IndexTracker(std::string const& name, TrackerContext& ctx, ITracker* parent, int size)
6259 : TrackerBase(name, ctx, parent),
6260 m_size(size),
6261 m_index(-1)
6262 {
6263 }
6264 virtual ~IndexTracker();
6265
acquire(TrackerContext & ctx,std::string const & name,int size)6266 static IndexTracker& acquire(TrackerContext& ctx, std::string const& name, int size)
6267 {
6268 IndexTracker* tracker = CATCH_NULL;
6269
6270 ITracker& currentTracker = ctx.currentTracker();
6271 if (ITracker* childTracker = currentTracker.findChild(name))
6272 {
6273 tracker = dynamic_cast<IndexTracker*>(childTracker);
6274 assert(tracker);
6275 }
6276 else
6277 {
6278 tracker = new IndexTracker(name, ctx, ¤tTracker, size);
6279 currentTracker.addChild(tracker);
6280 }
6281
6282 if (!ctx.completedCycle() && !tracker->isComplete())
6283 {
6284 if (tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun)
6285 tracker->moveNext();
6286 tracker->open();
6287 }
6288
6289 return *tracker;
6290 }
6291
index() const6292 int index() const { return m_index; }
6293
moveNext()6294 void moveNext()
6295 {
6296 m_index++;
6297 m_children.clear();
6298 }
6299
close()6300 virtual void close() CATCH_OVERRIDE
6301 {
6302 TrackerBase::close();
6303 if (m_runState == CompletedSuccessfully && m_index < m_size - 1)
6304 m_runState = Executing;
6305 }
6306 };
6307
startRun()6308 inline ITracker& TrackerContext::startRun()
6309 {
6310 m_rootTracker = new SectionTracker("{root}", *this, CATCH_NULL);
6311 m_currentTracker = CATCH_NULL;
6312 m_runState = Executing;
6313 return *m_rootTracker;
6314 }
6315
6316 } // namespace TestCaseTracking
6317
6318 using TestCaseTracking::ITracker;
6319 using TestCaseTracking::TrackerContext;
6320 using TestCaseTracking::SectionTracker;
6321 using TestCaseTracking::IndexTracker;
6322
6323 } // namespace Catch
6324
6325 // #included from: catch_fatal_condition.hpp
6326 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
6327
6328 namespace Catch {
6329
6330 // Report the error condition then exit the process
fatal(std::string const & message,int exitCode)6331 inline void fatal(std::string const& message, int exitCode)
6332 {
6333 IContext& context = Catch::getCurrentContext();
6334 IResultCapture* resultCapture = context.getResultCapture();
6335 resultCapture->handleFatalErrorCondition(message);
6336
6337 if (Catch::alwaysTrue()) // avoids "no return" warnings
6338 exit(exitCode);
6339 }
6340
6341 } // namespace Catch
6342
6343 #if defined(CATCH_PLATFORM_WINDOWS) /////////////////////////////////////////
6344
6345 namespace Catch {
6346
6347 struct FatalConditionHandler
6348 {
resetCatch::FatalConditionHandler6349 void reset() {}
6350 };
6351
6352 } // namespace Catch
6353
6354 #else // Not Windows - assumed to be POSIX compatible //////////////////////////
6355
6356 #include <signal.h>
6357
6358 namespace Catch {
6359
6360 struct SignalDefs
6361 {
6362 int id;
6363 const char* name;
6364 };
6365 extern SignalDefs signalDefs[];
6366 SignalDefs signalDefs[] = {
6367 {SIGINT, "SIGINT - Terminal interrupt signal"},
6368 {SIGILL, "SIGILL - Illegal instruction signal"},
6369 {SIGFPE, "SIGFPE - Floating point error signal"},
6370 {SIGSEGV, "SIGSEGV - Segmentation violation signal"},
6371 {SIGTERM, "SIGTERM - Termination request signal"},
6372 {SIGABRT, "SIGABRT - Abort (abnormal termination) signal"}};
6373
6374 struct FatalConditionHandler
6375 {
6376
handleSignalCatch::FatalConditionHandler6377 static void handleSignal(int sig)
6378 {
6379 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i)
6380 if (sig == signalDefs[i].id)
6381 fatal(signalDefs[i].name, -sig);
6382 fatal("<unknown signal>", -sig);
6383 }
6384
FatalConditionHandlerCatch::FatalConditionHandler6385 FatalConditionHandler() : m_isSet(true)
6386 {
6387 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i)
6388 signal(signalDefs[i].id, handleSignal);
6389 }
~FatalConditionHandlerCatch::FatalConditionHandler6390 ~FatalConditionHandler()
6391 {
6392 reset();
6393 }
resetCatch::FatalConditionHandler6394 void reset()
6395 {
6396 if (m_isSet)
6397 {
6398 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i)
6399 signal(signalDefs[i].id, SIG_DFL);
6400 m_isSet = false;
6401 }
6402 }
6403
6404 bool m_isSet;
6405 };
6406
6407 } // namespace Catch
6408
6409 #endif // not Windows
6410
6411 #include <set>
6412 #include <string>
6413
6414 namespace Catch {
6415
6416 class StreamRedirect
6417 {
6418
6419 public:
StreamRedirect(std::ostream & stream,std::string & targetString)6420 StreamRedirect(std::ostream& stream, std::string& targetString)
6421 : m_stream(stream),
6422 m_prevBuf(stream.rdbuf()),
6423 m_targetString(targetString)
6424 {
6425 stream.rdbuf(m_oss.rdbuf());
6426 }
6427
~StreamRedirect()6428 ~StreamRedirect()
6429 {
6430 m_targetString += m_oss.str();
6431 m_stream.rdbuf(m_prevBuf);
6432 }
6433
6434 private:
6435 std::ostream& m_stream;
6436 std::streambuf* m_prevBuf;
6437 std::ostringstream m_oss;
6438 std::string& m_targetString;
6439 };
6440
6441 ///////////////////////////////////////////////////////////////////////////
6442
6443 class RunContext : public IResultCapture, public IRunner
6444 {
6445
6446 RunContext(RunContext const&);
6447 void operator=(RunContext const&);
6448
6449 public:
RunContext(Ptr<IConfig const> const & _config,Ptr<IStreamingReporter> const & reporter)6450 explicit RunContext(Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter)
6451 : m_runInfo(_config->name()),
6452 m_context(getCurrentMutableContext()),
6453 m_activeTestCase(CATCH_NULL),
6454 m_config(_config),
6455 m_reporter(reporter)
6456 {
6457 m_context.setRunner(this);
6458 m_context.setConfig(m_config);
6459 m_context.setResultCapture(this);
6460 m_reporter->testRunStarting(m_runInfo);
6461 }
6462
~RunContext()6463 virtual ~RunContext()
6464 {
6465 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
6466 }
6467
testGroupStarting(std::string const & testSpec,std::size_t groupIndex,std::size_t groupsCount)6468 void testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount)
6469 {
6470 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
6471 }
testGroupEnded(std::string const & testSpec,Totals const & totals,std::size_t groupIndex,std::size_t groupsCount)6472 void testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount)
6473 {
6474 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
6475 }
6476
runTest(TestCase const & testCase)6477 Totals runTest(TestCase const& testCase)
6478 {
6479 Totals prevTotals = m_totals;
6480
6481 std::string redirectedCout;
6482 std::string redirectedCerr;
6483
6484 TestCaseInfo testInfo = testCase.getTestCaseInfo();
6485
6486 m_reporter->testCaseStarting(testInfo);
6487
6488 m_activeTestCase = &testCase;
6489
6490 do
6491 {
6492 m_trackerContext.startRun();
6493 do
6494 {
6495 m_trackerContext.startCycle();
6496 m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, testInfo.name);
6497 runCurrentTest(redirectedCout, redirectedCerr);
6498 } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
6499 }
6500 // !TBD: deprecated - this will be replaced by indexed trackers
6501 while (getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting());
6502
6503 Totals deltaTotals = m_totals.delta(prevTotals);
6504 m_totals.testCases += deltaTotals.testCases;
6505 m_reporter->testCaseEnded(TestCaseStats(testInfo,
6506 deltaTotals,
6507 redirectedCout,
6508 redirectedCerr,
6509 aborting()));
6510
6511 m_activeTestCase = CATCH_NULL;
6512 m_testCaseTracker = CATCH_NULL;
6513
6514 return deltaTotals;
6515 }
6516
config() const6517 Ptr<IConfig const> config() const
6518 {
6519 return m_config;
6520 }
6521
6522 private: // IResultCapture
assertionEnded(AssertionResult const & result)6523 virtual void assertionEnded(AssertionResult const& result)
6524 {
6525 if (result.getResultType() == ResultWas::Ok)
6526 {
6527 m_totals.assertions.passed++;
6528 }
6529 else if (!result.isOk())
6530 {
6531 m_totals.assertions.failed++;
6532 }
6533
6534 if (m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)))
6535 m_messages.clear();
6536
6537 // Reset working state
6538 m_lastAssertionInfo = AssertionInfo("", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}", m_lastAssertionInfo.resultDisposition);
6539 m_lastResult = result;
6540 }
6541
sectionStarted(SectionInfo const & sectionInfo,Counts & assertions)6542 virtual bool sectionStarted(
6543 SectionInfo const& sectionInfo,
6544 Counts& assertions)
6545 {
6546 std::ostringstream oss;
6547 oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
6548
6549 ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, oss.str());
6550 if (!sectionTracker.isOpen())
6551 return false;
6552 m_activeSections.push_back(§ionTracker);
6553
6554 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
6555
6556 m_reporter->sectionStarting(sectionInfo);
6557
6558 assertions = m_totals.assertions;
6559
6560 return true;
6561 }
testForMissingAssertions(Counts & assertions)6562 bool testForMissingAssertions(Counts& assertions)
6563 {
6564 if (assertions.total() != 0)
6565 return false;
6566 if (!m_config->warnAboutMissingAssertions())
6567 return false;
6568 if (m_trackerContext.currentTracker().hasChildren())
6569 return false;
6570 m_totals.assertions.failed++;
6571 assertions.failed++;
6572 return true;
6573 }
6574
sectionEnded(SectionEndInfo const & endInfo)6575 virtual void sectionEnded(SectionEndInfo const& endInfo)
6576 {
6577 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
6578 bool missingAssertions = testForMissingAssertions(assertions);
6579
6580 if (!m_activeSections.empty())
6581 {
6582 m_activeSections.back()->close();
6583 m_activeSections.pop_back();
6584 }
6585
6586 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
6587 m_messages.clear();
6588 }
6589
sectionEndedEarly(SectionEndInfo const & endInfo)6590 virtual void sectionEndedEarly(SectionEndInfo const& endInfo)
6591 {
6592 if (m_unfinishedSections.empty())
6593 m_activeSections.back()->fail();
6594 else
6595 m_activeSections.back()->close();
6596 m_activeSections.pop_back();
6597
6598 m_unfinishedSections.push_back(endInfo);
6599 }
6600
pushScopedMessage(MessageInfo const & message)6601 virtual void pushScopedMessage(MessageInfo const& message)
6602 {
6603 m_messages.push_back(message);
6604 }
6605
popScopedMessage(MessageInfo const & message)6606 virtual void popScopedMessage(MessageInfo const& message)
6607 {
6608 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
6609 }
6610
getCurrentTestName() const6611 virtual std::string getCurrentTestName() const
6612 {
6613 return m_activeTestCase
6614 ? m_activeTestCase->getTestCaseInfo().name
6615 : "";
6616 }
6617
getLastResult() const6618 virtual const AssertionResult* getLastResult() const
6619 {
6620 return &m_lastResult;
6621 }
6622
handleFatalErrorCondition(std::string const & message)6623 virtual void handleFatalErrorCondition(std::string const& message)
6624 {
6625 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
6626 resultBuilder.setResultType(ResultWas::FatalErrorCondition);
6627 resultBuilder << message;
6628 resultBuilder.captureExpression();
6629
6630 handleUnfinishedSections();
6631
6632 // Recreate section for test case (as we will lose the one that was in scope)
6633 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6634 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
6635
6636 Counts assertions;
6637 assertions.failed = 1;
6638 SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
6639 m_reporter->sectionEnded(testCaseSectionStats);
6640
6641 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
6642
6643 Totals deltaTotals;
6644 deltaTotals.testCases.failed = 1;
6645 m_reporter->testCaseEnded(TestCaseStats(testInfo,
6646 deltaTotals,
6647 "",
6648 "",
6649 false));
6650 m_totals.testCases.failed++;
6651 testGroupEnded("", m_totals, 1, 1);
6652 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
6653 }
6654
6655 public:
6656 // !TBD We need to do this another way!
aborting() const6657 bool aborting() const
6658 {
6659 return m_totals.assertions.failed == static_cast<std::size_t>(m_config->abortAfter());
6660 }
6661
6662 private:
runCurrentTest(std::string & redirectedCout,std::string & redirectedCerr)6663 void runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr)
6664 {
6665 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6666 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
6667 m_reporter->sectionStarting(testCaseSection);
6668 Counts prevAssertions = m_totals.assertions;
6669 double duration = 0;
6670 try
6671 {
6672 m_lastAssertionInfo = AssertionInfo("TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal);
6673
6674 seedRng(*m_config);
6675
6676 Timer timer;
6677 timer.start();
6678 if (m_reporter->getPreferences().shouldRedirectStdOut)
6679 {
6680 StreamRedirect coutRedir(Catch::cout(), redirectedCout);
6681 StreamRedirect cerrRedir(Catch::cerr(), redirectedCerr);
6682 invokeActiveTestCase();
6683 }
6684 else
6685 {
6686 invokeActiveTestCase();
6687 }
6688 duration = timer.getElapsedSeconds();
6689 }
6690 catch (TestFailureException&)
6691 {
6692 // This just means the test was aborted due to failure
6693 }
6694 catch (...)
6695 {
6696 makeUnexpectedResultBuilder().useActiveException();
6697 }
6698 m_testCaseTracker->close();
6699 handleUnfinishedSections();
6700 m_messages.clear();
6701
6702 Counts assertions = m_totals.assertions - prevAssertions;
6703 bool missingAssertions = testForMissingAssertions(assertions);
6704
6705 if (testCaseInfo.okToFail())
6706 {
6707 std::swap(assertions.failedButOk, assertions.failed);
6708 m_totals.assertions.failed -= assertions.failedButOk;
6709 m_totals.assertions.failedButOk += assertions.failedButOk;
6710 }
6711
6712 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
6713 m_reporter->sectionEnded(testCaseSectionStats);
6714 }
6715
invokeActiveTestCase()6716 void invokeActiveTestCase()
6717 {
6718 FatalConditionHandler fatalConditionHandler; // Handle signals
6719 m_activeTestCase->invoke();
6720 fatalConditionHandler.reset();
6721 }
6722
6723 private:
makeUnexpectedResultBuilder() const6724 ResultBuilder makeUnexpectedResultBuilder() const
6725 {
6726 return ResultBuilder(m_lastAssertionInfo.macroName.c_str(),
6727 m_lastAssertionInfo.lineInfo,
6728 m_lastAssertionInfo.capturedExpression.c_str(),
6729 m_lastAssertionInfo.resultDisposition);
6730 }
6731
handleUnfinishedSections()6732 void handleUnfinishedSections()
6733 {
6734 // If sections ended prematurely due to an exception we stored their
6735 // infos here so we can tear them down outside the unwind process.
6736 for (std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
6737 itEnd = m_unfinishedSections.rend();
6738 it != itEnd;
6739 ++it)
6740 sectionEnded(*it);
6741 m_unfinishedSections.clear();
6742 }
6743
6744 TestRunInfo m_runInfo;
6745 IMutableContext& m_context;
6746 TestCase const* m_activeTestCase;
6747 ITracker* m_testCaseTracker;
6748 ITracker* m_currentSectionTracker;
6749 AssertionResult m_lastResult;
6750
6751 Ptr<IConfig const> m_config;
6752 Totals m_totals;
6753 Ptr<IStreamingReporter> m_reporter;
6754 std::vector<MessageInfo> m_messages;
6755 AssertionInfo m_lastAssertionInfo;
6756 std::vector<SectionEndInfo> m_unfinishedSections;
6757 std::vector<ITracker*> m_activeSections;
6758 TrackerContext m_trackerContext;
6759 };
6760
getResultCapture()6761 IResultCapture& getResultCapture()
6762 {
6763 if (IResultCapture* capture = getCurrentContext().getResultCapture())
6764 return *capture;
6765 else
6766 throw std::logic_error("No result capture instance");
6767 }
6768
6769 } // end namespace Catch
6770
6771 // #included from: internal/catch_version.h
6772 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
6773
6774 namespace Catch {
6775
6776 // Versioning information
6777 struct Version
6778 {
6779 Version(unsigned int _majorVersion,
6780 unsigned int _minorVersion,
6781 unsigned int _patchNumber,
6782 std::string const& _branchName,
6783 unsigned int _buildNumber);
6784
6785 unsigned int const majorVersion;
6786 unsigned int const minorVersion;
6787 unsigned int const patchNumber;
6788
6789 // buildNumber is only used if branchName is not null
6790 std::string const branchName;
6791 unsigned int const buildNumber;
6792
6793 friend std::ostream& operator<<(std::ostream& os, Version const& version);
6794
6795 private:
6796 void operator=(Version const&);
6797 };
6798
6799 extern Version libraryVersion;
6800 }
6801
6802 #include <fstream>
6803 #include <limits>
6804 #include <stdlib.h>
6805
6806 namespace Catch {
6807
createReporter(std::string const & reporterName,Ptr<Config> const & config)6808 Ptr<IStreamingReporter> createReporter(std::string const& reporterName, Ptr<Config> const& config)
6809 {
6810 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create(reporterName, config.get());
6811 if (!reporter)
6812 {
6813 std::ostringstream oss;
6814 oss << "No reporter registered with name: '" << reporterName << "'";
6815 throw std::domain_error(oss.str());
6816 }
6817 return reporter;
6818 }
6819
makeReporter(Ptr<Config> const & config)6820 Ptr<IStreamingReporter> makeReporter(Ptr<Config> const& config)
6821 {
6822 std::vector<std::string> reporters = config->getReporterNames();
6823 if (reporters.empty())
6824 reporters.push_back("console");
6825
6826 Ptr<IStreamingReporter> reporter;
6827 for (std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
6828 it != itEnd;
6829 ++it)
6830 reporter = addReporter(reporter, createReporter(*it, config));
6831 return reporter;
6832 }
addListeners(Ptr<IConfig const> const & config,Ptr<IStreamingReporter> reporters)6833 Ptr<IStreamingReporter> addListeners(Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters)
6834 {
6835 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
6836 for (IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
6837 it != itEnd;
6838 ++it)
6839 reporters = addReporter(reporters, (*it)->create(ReporterConfig(config)));
6840 return reporters;
6841 }
6842
runTests(Ptr<Config> const & config)6843 Totals runTests(Ptr<Config> const& config)
6844 {
6845
6846 Ptr<IConfig const> iconfig = config.get();
6847
6848 Ptr<IStreamingReporter> reporter = makeReporter(config);
6849 reporter = addListeners(iconfig, reporter);
6850
6851 RunContext context(iconfig, reporter);
6852
6853 Totals totals;
6854
6855 context.testGroupStarting(config->name(), 1, 1);
6856
6857 TestSpec testSpec = config->testSpec();
6858 if (!testSpec.hasFilters())
6859 testSpec = TestSpecParser(ITagAliasRegistry::get()).parse("~[.]").testSpec(); // All not hidden tests
6860
6861 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted(*iconfig);
6862 for (std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
6863 it != itEnd;
6864 ++it)
6865 {
6866 if (!context.aborting() && matchTest(*it, testSpec, *iconfig))
6867 totals += context.runTest(*it);
6868 else
6869 reporter->skipTest(*it);
6870 }
6871
6872 context.testGroupEnded(iconfig->name(), totals, 1, 1);
6873 return totals;
6874 }
6875
applyFilenamesAsTags(IConfig const & config)6876 void applyFilenamesAsTags(IConfig const& config)
6877 {
6878 std::vector<TestCase> const& tests = getAllTestCasesSorted(config);
6879 for (std::size_t i = 0; i < tests.size(); ++i)
6880 {
6881 TestCase& test = const_cast<TestCase&>(tests[i]);
6882 std::set<std::string> tags = test.tags;
6883
6884 std::string filename = test.lineInfo.file;
6885 std::string::size_type lastSlash = filename.find_last_of("\\/");
6886 if (lastSlash != std::string::npos)
6887 filename = filename.substr(lastSlash + 1);
6888
6889 std::string::size_type lastDot = filename.find_last_of(".");
6890 if (lastDot != std::string::npos)
6891 filename = filename.substr(0, lastDot);
6892
6893 tags.insert("#" + filename);
6894 setTags(test, tags);
6895 }
6896 }
6897
6898 class Session : NonCopyable
6899 {
6900 static bool alreadyInstantiated;
6901
6902 public:
6903 struct OnUnusedOptions
6904 {
6905 enum DoWhat
6906 {
6907 Ignore,
6908 Fail
6909 };
6910 };
6911
Session()6912 Session()
6913 : m_cli(makeCommandLineParser())
6914 {
6915 if (alreadyInstantiated)
6916 {
6917 std::string msg = "Only one instance of Catch::Session can ever be used";
6918 Catch::cerr() << msg << std::endl;
6919 throw std::logic_error(msg);
6920 }
6921 alreadyInstantiated = true;
6922 }
~Session()6923 ~Session()
6924 {
6925 Catch::cleanUp();
6926 }
6927
showHelp(std::string const & processName)6928 void showHelp(std::string const& processName)
6929 {
6930 Catch::cout() << "\nCatch v" << libraryVersion << "\n";
6931
6932 m_cli.usage(Catch::cout(), processName);
6933 Catch::cout() << "For more detail usage please see the project docs\n"
6934 << std::endl;
6935 }
6936
applyCommandLine(int argc,char const * const argv[],OnUnusedOptions::DoWhat unusedOptionBehaviour=OnUnusedOptions::Fail)6937 int applyCommandLine(int argc, char const* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail)
6938 {
6939 try
6940 {
6941 m_cli.setThrowOnUnrecognisedTokens(unusedOptionBehaviour == OnUnusedOptions::Fail);
6942 m_unusedTokens = m_cli.parseInto(argc, argv, m_configData);
6943 if (m_configData.showHelp)
6944 showHelp(m_configData.processName);
6945 m_config.reset();
6946 }
6947 catch (std::exception& ex)
6948 {
6949 {
6950 Colour colourGuard(Colour::Red);
6951 Catch::cerr()
6952 << "\nError(s) in input:\n"
6953 << Text(ex.what(), TextAttributes().setIndent(2))
6954 << "\n\n";
6955 }
6956 m_cli.usage(Catch::cout(), m_configData.processName);
6957 return (std::numeric_limits<int>::max)();
6958 }
6959 return 0;
6960 }
6961
useConfigData(ConfigData const & _configData)6962 void useConfigData(ConfigData const& _configData)
6963 {
6964 m_configData = _configData;
6965 m_config.reset();
6966 }
6967
run(int argc,char const * const argv[])6968 int run(int argc, char const* const argv[])
6969 {
6970
6971 int returnCode = applyCommandLine(argc, argv);
6972 if (returnCode == 0)
6973 returnCode = run();
6974 return returnCode;
6975 }
6976
run()6977 int run()
6978 {
6979 if (m_configData.showHelp)
6980 return 0;
6981
6982 try
6983 {
6984 config(); // Force config to be constructed
6985
6986 seedRng(*m_config);
6987
6988 if (m_configData.filenamesAsTags)
6989 applyFilenamesAsTags(*m_config);
6990
6991 // Handle list request
6992 if (Option<std::size_t> listed = list(config()))
6993 return static_cast<int>(*listed);
6994
6995 return static_cast<int>(runTests(m_config).assertions.failed);
6996 }
6997 catch (std::exception& ex)
6998 {
6999 Catch::cerr() << ex.what() << std::endl;
7000 return (std::numeric_limits<int>::max)();
7001 }
7002 }
7003
cli() const7004 Clara::CommandLine<ConfigData> const& cli() const
7005 {
7006 return m_cli;
7007 }
unusedTokens() const7008 std::vector<Clara::Parser::Token> const& unusedTokens() const
7009 {
7010 return m_unusedTokens;
7011 }
configData()7012 ConfigData& configData()
7013 {
7014 return m_configData;
7015 }
config()7016 Config& config()
7017 {
7018 if (!m_config)
7019 m_config = new Config(m_configData);
7020 return *m_config;
7021 }
7022
7023 private:
7024 Clara::CommandLine<ConfigData> m_cli;
7025 std::vector<Clara::Parser::Token> m_unusedTokens;
7026 ConfigData m_configData;
7027 Ptr<Config> m_config;
7028 };
7029
7030 bool Session::alreadyInstantiated = false;
7031
7032 } // end namespace Catch
7033
7034 // #included from: catch_registry_hub.hpp
7035 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
7036
7037 // #included from: catch_test_case_registry_impl.hpp
7038 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
7039
7040 #include <algorithm>
7041 #include <iostream>
7042 #include <set>
7043 #include <sstream>
7044 #include <vector>
7045
7046 namespace Catch {
7047
7048 struct LexSort
7049 {
operator ()Catch::LexSort7050 bool operator()(TestCase i, TestCase j) const { return (i < j); }
7051 };
7052 struct RandomNumberGenerator
7053 {
operator ()Catch::RandomNumberGenerator7054 int operator()(int n) const { return std::rand() % n; }
7055 };
7056
sortTests(IConfig const & config,std::vector<TestCase> const & unsortedTestCases)7057 inline std::vector<TestCase> sortTests(IConfig const& config, std::vector<TestCase> const& unsortedTestCases)
7058 {
7059
7060 std::vector<TestCase> sorted = unsortedTestCases;
7061
7062 switch (config.runOrder())
7063 {
7064 case RunTests::InLexicographicalOrder:
7065 std::sort(sorted.begin(), sorted.end(), LexSort());
7066 break;
7067 case RunTests::InRandomOrder:
7068 {
7069 seedRng(config);
7070
7071 RandomNumberGenerator rng;
7072 std::random_shuffle(sorted.begin(), sorted.end(), rng);
7073 }
7074 break;
7075 case RunTests::InDeclarationOrder:
7076 // already in declaration order
7077 break;
7078 }
7079 return sorted;
7080 }
matchTest(TestCase const & testCase,TestSpec const & testSpec,IConfig const & config)7081 bool matchTest(TestCase const& testCase, TestSpec const& testSpec, IConfig const& config)
7082 {
7083 return testSpec.matches(testCase) && (config.allowThrows() || !testCase.throws());
7084 }
7085
enforceNoDuplicateTestCases(std::vector<TestCase> const & functions)7086 void enforceNoDuplicateTestCases(std::vector<TestCase> const& functions)
7087 {
7088 std::set<TestCase> seenFunctions;
7089 for (std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
7090 it != itEnd;
7091 ++it)
7092 {
7093 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert(*it);
7094 if (!prev.second)
7095 {
7096 Catch::cerr()
7097 << Colour(Colour::Red)
7098 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
7099 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
7100 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
7101 exit(1);
7102 }
7103 }
7104 }
7105
filterTests(std::vector<TestCase> const & testCases,TestSpec const & testSpec,IConfig const & config)7106 std::vector<TestCase> filterTests(std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config)
7107 {
7108 std::vector<TestCase> filtered;
7109 filtered.reserve(testCases.size());
7110 for (std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
7111 it != itEnd;
7112 ++it)
7113 if (matchTest(*it, testSpec, config))
7114 filtered.push_back(*it);
7115 return filtered;
7116 }
getAllTestCasesSorted(IConfig const & config)7117 std::vector<TestCase> const& getAllTestCasesSorted(IConfig const& config)
7118 {
7119 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted(config);
7120 }
7121
7122 class TestRegistry : public ITestCaseRegistry
7123 {
7124 public:
TestRegistry()7125 TestRegistry()
7126 : m_currentSortOrder(RunTests::InDeclarationOrder),
7127 m_unnamedCount(0)
7128 {
7129 }
7130 virtual ~TestRegistry();
7131
registerTest(TestCase const & testCase)7132 virtual void registerTest(TestCase const& testCase)
7133 {
7134 std::string name = testCase.getTestCaseInfo().name;
7135 if (name == "")
7136 {
7137 std::ostringstream oss;
7138 oss << "Anonymous test case " << ++m_unnamedCount;
7139 return registerTest(testCase.withName(oss.str()));
7140 }
7141 m_functions.push_back(testCase);
7142 }
7143
getAllTests() const7144 virtual std::vector<TestCase> const& getAllTests() const
7145 {
7146 return m_functions;
7147 }
getAllTestsSorted(IConfig const & config) const7148 virtual std::vector<TestCase> const& getAllTestsSorted(IConfig const& config) const
7149 {
7150 if (m_sortedFunctions.empty())
7151 enforceNoDuplicateTestCases(m_functions);
7152
7153 if (m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty())
7154 {
7155 m_sortedFunctions = sortTests(config, m_functions);
7156 m_currentSortOrder = config.runOrder();
7157 }
7158 return m_sortedFunctions;
7159 }
7160
7161 private:
7162 std::vector<TestCase> m_functions;
7163 mutable RunTests::InWhatOrder m_currentSortOrder;
7164 mutable std::vector<TestCase> m_sortedFunctions;
7165 size_t m_unnamedCount;
7166 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
7167 };
7168
7169 ///////////////////////////////////////////////////////////////////////////
7170
7171 class FreeFunctionTestCase : public SharedImpl<ITestCase>
7172 {
7173 public:
FreeFunctionTestCase(TestFunction fun)7174 FreeFunctionTestCase(TestFunction fun) : m_fun(fun) {}
7175
invoke() const7176 virtual void invoke() const
7177 {
7178 m_fun();
7179 }
7180
7181 private:
7182 virtual ~FreeFunctionTestCase();
7183
7184 TestFunction m_fun;
7185 };
7186
extractClassName(std::string const & classOrQualifiedMethodName)7187 inline std::string extractClassName(std::string const& classOrQualifiedMethodName)
7188 {
7189 std::string className = classOrQualifiedMethodName;
7190 if (startsWith(className, "&"))
7191 {
7192 std::size_t lastColons = className.rfind("::");
7193 std::size_t penultimateColons = className.rfind("::", lastColons - 1);
7194 if (penultimateColons == std::string::npos)
7195 penultimateColons = 1;
7196 className = className.substr(penultimateColons, lastColons - penultimateColons);
7197 }
7198 return className;
7199 }
7200
registerTestCase(ITestCase * testCase,char const * classOrQualifiedMethodName,NameAndDesc const & nameAndDesc,SourceLineInfo const & lineInfo)7201 void registerTestCase(ITestCase* testCase,
7202 char const* classOrQualifiedMethodName,
7203 NameAndDesc const& nameAndDesc,
7204 SourceLineInfo const& lineInfo)
7205 {
7206
7207 getMutableRegistryHub().registerTest(makeTestCase(testCase,
7208 extractClassName(classOrQualifiedMethodName),
7209 nameAndDesc.name,
7210 nameAndDesc.description,
7211 lineInfo));
7212 }
registerTestCaseFunction(TestFunction function,SourceLineInfo const & lineInfo,NameAndDesc const & nameAndDesc)7213 void registerTestCaseFunction(TestFunction function,
7214 SourceLineInfo const& lineInfo,
7215 NameAndDesc const& nameAndDesc)
7216 {
7217 registerTestCase(new FreeFunctionTestCase(function), "", nameAndDesc, lineInfo);
7218 }
7219
7220 ///////////////////////////////////////////////////////////////////////////
7221
AutoReg(TestFunction function,SourceLineInfo const & lineInfo,NameAndDesc const & nameAndDesc)7222 AutoReg::AutoReg(TestFunction function,
7223 SourceLineInfo const& lineInfo,
7224 NameAndDesc const& nameAndDesc)
7225 {
7226 registerTestCaseFunction(function, lineInfo, nameAndDesc);
7227 }
7228
~AutoReg()7229 AutoReg::~AutoReg() {}
7230
7231 } // end namespace Catch
7232
7233 // #included from: catch_reporter_registry.hpp
7234 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
7235
7236 #include <map>
7237
7238 namespace Catch {
7239
7240 class ReporterRegistry : public IReporterRegistry
7241 {
7242
7243 public:
~ReporterRegistry()7244 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
7245
create(std::string const & name,Ptr<IConfig const> const & config) const7246 virtual IStreamingReporter* create(std::string const& name, Ptr<IConfig const> const& config) const CATCH_OVERRIDE
7247 {
7248 FactoryMap::const_iterator it = m_factories.find(name);
7249 if (it == m_factories.end())
7250 return CATCH_NULL;
7251 return it->second->create(ReporterConfig(config));
7252 }
7253
registerReporter(std::string const & name,Ptr<IReporterFactory> const & factory)7254 void registerReporter(std::string const& name, Ptr<IReporterFactory> const& factory)
7255 {
7256 m_factories.insert(std::make_pair(name, factory));
7257 }
registerListener(Ptr<IReporterFactory> const & factory)7258 void registerListener(Ptr<IReporterFactory> const& factory)
7259 {
7260 m_listeners.push_back(factory);
7261 }
7262
getFactories() const7263 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE
7264 {
7265 return m_factories;
7266 }
getListeners() const7267 virtual Listeners const& getListeners() const CATCH_OVERRIDE
7268 {
7269 return m_listeners;
7270 }
7271
7272 private:
7273 FactoryMap m_factories;
7274 Listeners m_listeners;
7275 };
7276 }
7277
7278 // #included from: catch_exception_translator_registry.hpp
7279 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
7280
7281 #ifdef __OBJC__
7282 #import "Foundation/Foundation.h"
7283 #endif
7284
7285 namespace Catch {
7286
7287 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry
7288 {
7289 public:
~ExceptionTranslatorRegistry()7290 ~ExceptionTranslatorRegistry()
7291 {
7292 deleteAll(m_translators);
7293 }
7294
registerTranslator(const IExceptionTranslator * translator)7295 virtual void registerTranslator(const IExceptionTranslator* translator)
7296 {
7297 m_translators.push_back(translator);
7298 }
7299
translateActiveException() const7300 virtual std::string translateActiveException() const
7301 {
7302 try
7303 {
7304 #ifdef __OBJC__
7305 // In Objective-C try objective-c exceptions first
7306 @try
7307 {
7308 return tryTranslators();
7309 }
7310 @catch (NSException* exception)
7311 {
7312 return Catch::toString([exception description]);
7313 }
7314 #else
7315 return tryTranslators();
7316 #endif
7317 }
7318 catch (TestFailureException&)
7319 {
7320 throw;
7321 }
7322 catch (std::exception& ex)
7323 {
7324 return ex.what();
7325 }
7326 catch (std::string& msg)
7327 {
7328 return msg;
7329 }
7330 catch (const char* msg)
7331 {
7332 return msg;
7333 }
7334 catch (...)
7335 {
7336 return "Unknown exception";
7337 }
7338 }
7339
tryTranslators() const7340 std::string tryTranslators() const
7341 {
7342 if (m_translators.empty())
7343 throw;
7344 else
7345 return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
7346 }
7347
7348 private:
7349 std::vector<const IExceptionTranslator*> m_translators;
7350 };
7351 }
7352
7353 namespace Catch {
7354
7355 namespace {
7356
7357 class RegistryHub : public IRegistryHub, public IMutableRegistryHub
7358 {
7359
7360 RegistryHub(RegistryHub const&);
7361 void operator=(RegistryHub const&);
7362
7363 public: // IRegistryHub
RegistryHub()7364 RegistryHub()
7365 {
7366 }
getReporterRegistry() const7367 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE
7368 {
7369 return m_reporterRegistry;
7370 }
getTestCaseRegistry() const7371 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE
7372 {
7373 return m_testCaseRegistry;
7374 }
getExceptionTranslatorRegistry()7375 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE
7376 {
7377 return m_exceptionTranslatorRegistry;
7378 }
7379
7380 public: // IMutableRegistryHub
registerReporter(std::string const & name,Ptr<IReporterFactory> const & factory)7381 virtual void registerReporter(std::string const& name, Ptr<IReporterFactory> const& factory) CATCH_OVERRIDE
7382 {
7383 m_reporterRegistry.registerReporter(name, factory);
7384 }
registerListener(Ptr<IReporterFactory> const & factory)7385 virtual void registerListener(Ptr<IReporterFactory> const& factory) CATCH_OVERRIDE
7386 {
7387 m_reporterRegistry.registerListener(factory);
7388 }
registerTest(TestCase const & testInfo)7389 virtual void registerTest(TestCase const& testInfo) CATCH_OVERRIDE
7390 {
7391 m_testCaseRegistry.registerTest(testInfo);
7392 }
registerTranslator(const IExceptionTranslator * translator)7393 virtual void registerTranslator(const IExceptionTranslator* translator) CATCH_OVERRIDE
7394 {
7395 m_exceptionTranslatorRegistry.registerTranslator(translator);
7396 }
7397
7398 private:
7399 TestRegistry m_testCaseRegistry;
7400 ReporterRegistry m_reporterRegistry;
7401 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
7402 };
7403
7404 // Single, global, instance
getTheRegistryHub()7405 inline RegistryHub*& getTheRegistryHub()
7406 {
7407 static RegistryHub* theRegistryHub = CATCH_NULL;
7408 if (!theRegistryHub)
7409 theRegistryHub = new RegistryHub();
7410 return theRegistryHub;
7411 }
7412 }
7413
getRegistryHub()7414 IRegistryHub& getRegistryHub()
7415 {
7416 return *getTheRegistryHub();
7417 }
getMutableRegistryHub()7418 IMutableRegistryHub& getMutableRegistryHub()
7419 {
7420 return *getTheRegistryHub();
7421 }
cleanUp()7422 void cleanUp()
7423 {
7424 delete getTheRegistryHub();
7425 getTheRegistryHub() = CATCH_NULL;
7426 cleanUpContext();
7427 }
translateActiveException()7428 std::string translateActiveException()
7429 {
7430 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
7431 }
7432
7433 } // end namespace Catch
7434
7435 // #included from: catch_notimplemented_exception.hpp
7436 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
7437
7438 #include <ostream>
7439
7440 namespace Catch {
7441
NotImplementedException(SourceLineInfo const & lineInfo)7442 NotImplementedException::NotImplementedException(SourceLineInfo const& lineInfo)
7443 : m_lineInfo(lineInfo)
7444 {
7445 std::ostringstream oss;
7446 oss << lineInfo << ": function ";
7447 oss << "not implemented";
7448 m_what = oss.str();
7449 }
7450
what() const7451 const char* NotImplementedException::what() const CATCH_NOEXCEPT
7452 {
7453 return m_what.c_str();
7454 }
7455
7456 } // end namespace Catch
7457
7458 // #included from: catch_context_impl.hpp
7459 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
7460
7461 // #included from: catch_stream.hpp
7462 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
7463
7464 #include <cstdio>
7465 #include <iostream>
7466 #include <stdexcept>
7467
7468 namespace Catch {
7469
7470 template <typename WriterF, size_t bufferSize = 256>
7471 class StreamBufImpl : public StreamBufBase
7472 {
7473 char data[bufferSize];
7474 WriterF m_writer;
7475
7476 public:
StreamBufImpl()7477 StreamBufImpl()
7478 {
7479 setp(data, data + sizeof(data));
7480 }
7481
~StreamBufImpl()7482 ~StreamBufImpl() CATCH_NOEXCEPT
7483 {
7484 sync();
7485 }
7486
7487 private:
overflow(int c)7488 int overflow(int c)
7489 {
7490 sync();
7491
7492 if (c != EOF)
7493 {
7494 if (pbase() == epptr())
7495 m_writer(std::string(1, static_cast<char>(c)));
7496 else
7497 sputc(static_cast<char>(c));
7498 }
7499 return 0;
7500 }
7501
sync()7502 int sync()
7503 {
7504 if (pbase() != pptr())
7505 {
7506 m_writer(std::string(pbase(), static_cast<std::string::size_type>(pptr() - pbase())));
7507 setp(pbase(), epptr());
7508 }
7509 return 0;
7510 }
7511 };
7512
7513 ///////////////////////////////////////////////////////////////////////////
7514
FileStream(std::string const & filename)7515 FileStream::FileStream(std::string const& filename)
7516 {
7517 m_ofs.open(filename.c_str());
7518 if (m_ofs.fail())
7519 {
7520 std::ostringstream oss;
7521 oss << "Unable to open file: '" << filename << "'";
7522 throw std::domain_error(oss.str());
7523 }
7524 }
7525
stream() const7526 std::ostream& FileStream::stream() const
7527 {
7528 return m_ofs;
7529 }
7530
7531 struct OutputDebugWriter
7532 {
7533
operator ()Catch::OutputDebugWriter7534 void operator()(std::string const& str)
7535 {
7536 writeToDebugConsole(str);
7537 }
7538 };
7539
DebugOutStream()7540 DebugOutStream::DebugOutStream()
7541 : m_streamBuf(new StreamBufImpl<OutputDebugWriter>()),
7542 m_os(m_streamBuf.get())
7543 {
7544 }
7545
stream() const7546 std::ostream& DebugOutStream::stream() const
7547 {
7548 return m_os;
7549 }
7550
7551 // Store the streambuf from cout up-front because
7552 // cout may get redirected when running tests
CoutStream()7553 CoutStream::CoutStream()
7554 : m_os(Catch::cout().rdbuf())
7555 {
7556 }
7557
stream() const7558 std::ostream& CoutStream::stream() const
7559 {
7560 return m_os;
7561 }
7562
7563 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
cout()7564 std::ostream& cout()
7565 {
7566 return std::cout;
7567 }
cerr()7568 std::ostream& cerr()
7569 {
7570 return std::cerr;
7571 }
7572 #endif
7573 }
7574
7575 namespace Catch {
7576
7577 class Context : public IMutableContext
7578 {
7579
Context()7580 Context() : m_config(CATCH_NULL), m_runner(CATCH_NULL), m_resultCapture(CATCH_NULL) {}
7581 Context(Context const&);
7582 void operator=(Context const&);
7583
7584 public: // IContext
getResultCapture()7585 virtual IResultCapture* getResultCapture()
7586 {
7587 return m_resultCapture;
7588 }
getRunner()7589 virtual IRunner* getRunner()
7590 {
7591 return m_runner;
7592 }
getGeneratorIndex(std::string const & fileInfo,size_t totalSize)7593 virtual size_t getGeneratorIndex(std::string const& fileInfo, size_t totalSize)
7594 {
7595 return getGeneratorsForCurrentTest()
7596 .getGeneratorInfo(fileInfo, totalSize)
7597 .getCurrentIndex();
7598 }
advanceGeneratorsForCurrentTest()7599 virtual bool advanceGeneratorsForCurrentTest()
7600 {
7601 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7602 return generators && generators->moveNext();
7603 }
7604
getConfig() const7605 virtual Ptr<IConfig const> getConfig() const
7606 {
7607 return m_config;
7608 }
7609
7610 public: // IMutableContext
setResultCapture(IResultCapture * resultCapture)7611 virtual void setResultCapture(IResultCapture* resultCapture)
7612 {
7613 m_resultCapture = resultCapture;
7614 }
setRunner(IRunner * runner)7615 virtual void setRunner(IRunner* runner)
7616 {
7617 m_runner = runner;
7618 }
setConfig(Ptr<IConfig const> const & config)7619 virtual void setConfig(Ptr<IConfig const> const& config)
7620 {
7621 m_config = config;
7622 }
7623
7624 friend IMutableContext& getCurrentMutableContext();
7625
7626 private:
findGeneratorsForCurrentTest()7627 IGeneratorsForTest* findGeneratorsForCurrentTest()
7628 {
7629 std::string testName = getResultCapture()->getCurrentTestName();
7630
7631 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
7632 m_generatorsByTestName.find(testName);
7633 return it != m_generatorsByTestName.end()
7634 ? it->second
7635 : CATCH_NULL;
7636 }
7637
getGeneratorsForCurrentTest()7638 IGeneratorsForTest& getGeneratorsForCurrentTest()
7639 {
7640 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7641 if (!generators)
7642 {
7643 std::string testName = getResultCapture()->getCurrentTestName();
7644 generators = createGeneratorsForTest();
7645 m_generatorsByTestName.insert(std::make_pair(testName, generators));
7646 }
7647 return *generators;
7648 }
7649
7650 private:
7651 Ptr<IConfig const> m_config;
7652 IRunner* m_runner;
7653 IResultCapture* m_resultCapture;
7654 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
7655 };
7656
7657 namespace {
7658 Context* currentContext = CATCH_NULL;
7659 }
getCurrentMutableContext()7660 IMutableContext& getCurrentMutableContext()
7661 {
7662 if (!currentContext)
7663 currentContext = new Context();
7664 return *currentContext;
7665 }
getCurrentContext()7666 IContext& getCurrentContext()
7667 {
7668 return getCurrentMutableContext();
7669 }
7670
cleanUpContext()7671 void cleanUpContext()
7672 {
7673 delete currentContext;
7674 currentContext = CATCH_NULL;
7675 }
7676 }
7677
7678 // #included from: catch_console_colour_impl.hpp
7679 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
7680
7681 namespace Catch {
7682 namespace {
7683
7684 struct IColourImpl
7685 {
~IColourImplCatch::__anon5602dd960411::IColourImpl7686 virtual ~IColourImpl() {}
7687 virtual void use(Colour::Code _colourCode) = 0;
7688 };
7689
7690 struct NoColourImpl : IColourImpl
7691 {
useCatch::__anon5602dd960411::NoColourImpl7692 void use(Colour::Code) {}
7693
instanceCatch::__anon5602dd960411::NoColourImpl7694 static IColourImpl* instance()
7695 {
7696 static NoColourImpl s_instance;
7697 return &s_instance;
7698 }
7699 };
7700
7701 } // anon namespace
7702 } // namespace Catch
7703
7704 #if !defined(CATCH_CONFIG_COLOUR_NONE) && !defined(CATCH_CONFIG_COLOUR_WINDOWS) && !defined(CATCH_CONFIG_COLOUR_ANSI)
7705 #ifdef CATCH_PLATFORM_WINDOWS
7706 #define CATCH_CONFIG_COLOUR_WINDOWS
7707 #else
7708 #define CATCH_CONFIG_COLOUR_ANSI
7709 #endif
7710 #endif
7711
7712 #if defined(CATCH_CONFIG_COLOUR_WINDOWS) /////////////////////////////////////////
7713
7714 #ifndef NOMINMAX
7715 #define NOMINMAX
7716 #endif
7717
7718 #ifdef __AFXDLL
7719 #include <AfxWin.h>
7720 #else
7721 #include <windows.h>
7722 #endif
7723
7724 namespace Catch {
7725 namespace {
7726
7727 class Win32ColourImpl : public IColourImpl
7728 {
7729 public:
Win32ColourImpl()7730 Win32ColourImpl() : stdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE))
7731 {
7732 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
7733 GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo);
7734 originalForegroundAttributes = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
7735 originalBackgroundAttributes = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
7736 }
7737
use(Colour::Code _colourCode)7738 virtual void use(Colour::Code _colourCode)
7739 {
7740 switch (_colourCode)
7741 {
7742 case Colour::None:
7743 return setTextAttribute(originalForegroundAttributes);
7744 case Colour::White:
7745 return setTextAttribute(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE);
7746 case Colour::Red:
7747 return setTextAttribute(FOREGROUND_RED);
7748 case Colour::Green:
7749 return setTextAttribute(FOREGROUND_GREEN);
7750 case Colour::Blue:
7751 return setTextAttribute(FOREGROUND_BLUE);
7752 case Colour::Cyan:
7753 return setTextAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN);
7754 case Colour::Yellow:
7755 return setTextAttribute(FOREGROUND_RED | FOREGROUND_GREEN);
7756 case Colour::Grey:
7757 return setTextAttribute(0);
7758
7759 case Colour::LightGrey:
7760 return setTextAttribute(FOREGROUND_INTENSITY);
7761 case Colour::BrightRed:
7762 return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_RED);
7763 case Colour::BrightGreen:
7764 return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_GREEN);
7765 case Colour::BrightWhite:
7766 return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE);
7767
7768 case Colour::Bright:
7769 throw std::logic_error("not a colour");
7770 }
7771 }
7772
7773 private:
setTextAttribute(WORD _textAttribute)7774 void setTextAttribute(WORD _textAttribute)
7775 {
7776 SetConsoleTextAttribute(stdoutHandle, _textAttribute | originalBackgroundAttributes);
7777 }
7778 HANDLE stdoutHandle;
7779 WORD originalForegroundAttributes;
7780 WORD originalBackgroundAttributes;
7781 };
7782
platformColourInstance()7783 IColourImpl* platformColourInstance()
7784 {
7785 static Win32ColourImpl s_instance;
7786 return &s_instance;
7787 }
7788
7789 } // end anon namespace
7790 } // end namespace Catch
7791
7792 #elif defined(CATCH_CONFIG_COLOUR_ANSI) //////////////////////////////////////
7793
7794 #include <unistd.h>
7795
7796 namespace Catch {
7797 namespace {
7798
7799 // use POSIX/ ANSI console terminal codes
7800 // Thanks to Adam Strzelecki for original contribution
7801 // (http://github.com/nanoant)
7802 // https://github.com/philsquared/Catch/pull/131
7803 class PosixColourImpl : public IColourImpl
7804 {
7805 public:
use(Colour::Code _colourCode)7806 virtual void use(Colour::Code _colourCode)
7807 {
7808 switch (_colourCode)
7809 {
7810 case Colour::None:
7811 case Colour::White:
7812 return setColour("[0m");
7813 case Colour::Red:
7814 return setColour("[0;31m");
7815 case Colour::Green:
7816 return setColour("[0;32m");
7817 case Colour::Blue:
7818 return setColour("[0:34m");
7819 case Colour::Cyan:
7820 return setColour("[0;36m");
7821 case Colour::Yellow:
7822 return setColour("[0;33m");
7823 case Colour::Grey:
7824 return setColour("[1;30m");
7825
7826 case Colour::LightGrey:
7827 return setColour("[0;37m");
7828 case Colour::BrightRed:
7829 return setColour("[1;31m");
7830 case Colour::BrightGreen:
7831 return setColour("[1;32m");
7832 case Colour::BrightWhite:
7833 return setColour("[1;37m");
7834
7835 case Colour::Bright:
7836 throw std::logic_error("not a colour");
7837 }
7838 }
instance()7839 static IColourImpl* instance()
7840 {
7841 static PosixColourImpl s_instance;
7842 return &s_instance;
7843 }
7844
7845 private:
setColour(const char * _escapeCode)7846 void setColour(const char* _escapeCode)
7847 {
7848 Catch::cout() << '\033' << _escapeCode;
7849 }
7850 };
7851
platformColourInstance()7852 IColourImpl* platformColourInstance()
7853 {
7854 Ptr<IConfig const> config = getCurrentContext().getConfig();
7855 return (config && config->forceColour()) || isatty(STDOUT_FILENO)
7856 ? PosixColourImpl::instance()
7857 : NoColourImpl::instance();
7858 }
7859
7860 } // end anon namespace
7861 } // end namespace Catch
7862
7863 #else // not Windows or ANSI ///////////////////////////////////////////////
7864
7865 namespace Catch {
7866
platformColourInstance()7867 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
7868
7869 } // end namespace Catch
7870
7871 #endif // Windows/ ANSI/ None
7872
7873 namespace Catch {
7874
Colour(Code _colourCode)7875 Colour::Colour(Code _colourCode) : m_moved(false) { use(_colourCode); }
Colour(Colour const & _other)7876 Colour::Colour(Colour const& _other) : m_moved(false) { const_cast<Colour&>(_other).m_moved = true; }
~Colour()7877 Colour::~Colour()
7878 {
7879 if (!m_moved) use(None);
7880 }
7881
use(Code _colourCode)7882 void Colour::use(Code _colourCode)
7883 {
7884 static IColourImpl* impl = isDebuggerActive()
7885 ? NoColourImpl::instance()
7886 : platformColourInstance();
7887 impl->use(_colourCode);
7888 }
7889
7890 } // end namespace Catch
7891
7892 // #included from: catch_generators_impl.hpp
7893 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
7894
7895 #include <map>
7896 #include <string>
7897 #include <vector>
7898
7899 namespace Catch {
7900
7901 struct GeneratorInfo : IGeneratorInfo
7902 {
7903
GeneratorInfoCatch::GeneratorInfo7904 GeneratorInfo(std::size_t size)
7905 : m_size(size),
7906 m_currentIndex(0)
7907 {
7908 }
7909
moveNextCatch::GeneratorInfo7910 bool moveNext()
7911 {
7912 if (++m_currentIndex == m_size)
7913 {
7914 m_currentIndex = 0;
7915 return false;
7916 }
7917 return true;
7918 }
7919
getCurrentIndexCatch::GeneratorInfo7920 std::size_t getCurrentIndex() const
7921 {
7922 return m_currentIndex;
7923 }
7924
7925 std::size_t m_size;
7926 std::size_t m_currentIndex;
7927 };
7928
7929 ///////////////////////////////////////////////////////////////////////////
7930
7931 class GeneratorsForTest : public IGeneratorsForTest
7932 {
7933
7934 public:
~GeneratorsForTest()7935 ~GeneratorsForTest()
7936 {
7937 deleteAll(m_generatorsInOrder);
7938 }
7939
getGeneratorInfo(std::string const & fileInfo,std::size_t size)7940 IGeneratorInfo& getGeneratorInfo(std::string const& fileInfo, std::size_t size)
7941 {
7942 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find(fileInfo);
7943 if (it == m_generatorsByName.end())
7944 {
7945 IGeneratorInfo* info = new GeneratorInfo(size);
7946 m_generatorsByName.insert(std::make_pair(fileInfo, info));
7947 m_generatorsInOrder.push_back(info);
7948 return *info;
7949 }
7950 return *it->second;
7951 }
7952
moveNext()7953 bool moveNext()
7954 {
7955 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
7956 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
7957 for (; it != itEnd; ++it)
7958 {
7959 if ((*it)->moveNext())
7960 return true;
7961 }
7962 return false;
7963 }
7964
7965 private:
7966 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
7967 std::vector<IGeneratorInfo*> m_generatorsInOrder;
7968 };
7969
createGeneratorsForTest()7970 IGeneratorsForTest* createGeneratorsForTest()
7971 {
7972 return new GeneratorsForTest();
7973 }
7974
7975 } // end namespace Catch
7976
7977 // #included from: catch_assertionresult.hpp
7978 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
7979
7980 namespace Catch {
7981
AssertionInfo(std::string const & _macroName,SourceLineInfo const & _lineInfo,std::string const & _capturedExpression,ResultDisposition::Flags _resultDisposition)7982 AssertionInfo::AssertionInfo(std::string const& _macroName,
7983 SourceLineInfo const& _lineInfo,
7984 std::string const& _capturedExpression,
7985 ResultDisposition::Flags _resultDisposition)
7986 : macroName(_macroName),
7987 lineInfo(_lineInfo),
7988 capturedExpression(_capturedExpression),
7989 resultDisposition(_resultDisposition)
7990 {
7991 }
7992
AssertionResult()7993 AssertionResult::AssertionResult() {}
7994
AssertionResult(AssertionInfo const & info,AssertionResultData const & data)7995 AssertionResult::AssertionResult(AssertionInfo const& info, AssertionResultData const& data)
7996 : m_info(info),
7997 m_resultData(data)
7998 {
7999 }
8000
~AssertionResult()8001 AssertionResult::~AssertionResult() {}
8002
8003 // Result was a success
succeeded() const8004 bool AssertionResult::succeeded() const
8005 {
8006 return Catch::isOk(m_resultData.resultType);
8007 }
8008
8009 // Result was a success, or failure is suppressed
isOk() const8010 bool AssertionResult::isOk() const
8011 {
8012 return Catch::isOk(m_resultData.resultType) || shouldSuppressFailure(m_info.resultDisposition);
8013 }
8014
getResultType() const8015 ResultWas::OfType AssertionResult::getResultType() const
8016 {
8017 return m_resultData.resultType;
8018 }
8019
hasExpression() const8020 bool AssertionResult::hasExpression() const
8021 {
8022 return !m_info.capturedExpression.empty();
8023 }
8024
hasMessage() const8025 bool AssertionResult::hasMessage() const
8026 {
8027 return !m_resultData.message.empty();
8028 }
8029
getExpression() const8030 std::string AssertionResult::getExpression() const
8031 {
8032 if (isFalseTest(m_info.resultDisposition))
8033 return "!" + m_info.capturedExpression;
8034 else
8035 return m_info.capturedExpression;
8036 }
getExpressionInMacro() const8037 std::string AssertionResult::getExpressionInMacro() const
8038 {
8039 if (m_info.macroName.empty())
8040 return m_info.capturedExpression;
8041 else
8042 return m_info.macroName + "( " + m_info.capturedExpression + " )";
8043 }
8044
hasExpandedExpression() const8045 bool AssertionResult::hasExpandedExpression() const
8046 {
8047 return hasExpression() && getExpandedExpression() != getExpression();
8048 }
8049
getExpandedExpression() const8050 std::string AssertionResult::getExpandedExpression() const
8051 {
8052 return m_resultData.reconstructedExpression;
8053 }
8054
getMessage() const8055 std::string AssertionResult::getMessage() const
8056 {
8057 return m_resultData.message;
8058 }
getSourceInfo() const8059 SourceLineInfo AssertionResult::getSourceInfo() const
8060 {
8061 return m_info.lineInfo;
8062 }
8063
getTestMacroName() const8064 std::string AssertionResult::getTestMacroName() const
8065 {
8066 return m_info.macroName;
8067 }
8068
8069 } // end namespace Catch
8070
8071 // #included from: catch_test_case_info.hpp
8072 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
8073
8074 namespace Catch {
8075
parseSpecialTag(std::string const & tag)8076 inline TestCaseInfo::SpecialProperties parseSpecialTag(std::string const& tag)
8077 {
8078 if (startsWith(tag, ".") ||
8079 tag == "hide" ||
8080 tag == "!hide")
8081 return TestCaseInfo::IsHidden;
8082 else if (tag == "!throws")
8083 return TestCaseInfo::Throws;
8084 else if (tag == "!shouldfail")
8085 return TestCaseInfo::ShouldFail;
8086 else if (tag == "!mayfail")
8087 return TestCaseInfo::MayFail;
8088 else
8089 return TestCaseInfo::None;
8090 }
isReservedTag(std::string const & tag)8091 inline bool isReservedTag(std::string const& tag)
8092 {
8093 return parseSpecialTag(tag) == TestCaseInfo::None && tag.size() > 0 && !isalnum(tag[0]);
8094 }
enforceNotReservedTag(std::string const & tag,SourceLineInfo const & _lineInfo)8095 inline void enforceNotReservedTag(std::string const& tag, SourceLineInfo const& _lineInfo)
8096 {
8097 if (isReservedTag(tag))
8098 {
8099 {
8100 Colour colourGuard(Colour::Red);
8101 Catch::cerr()
8102 << "Tag name [" << tag << "] not allowed.\n"
8103 << "Tag names starting with non alpha-numeric characters are reserved\n";
8104 }
8105 {
8106 Colour colourGuard(Colour::FileName);
8107 Catch::cerr() << _lineInfo << std::endl;
8108 }
8109 exit(1);
8110 }
8111 }
8112
makeTestCase(ITestCase * _testCase,std::string const & _className,std::string const & _name,std::string const & _descOrTags,SourceLineInfo const & _lineInfo)8113 TestCase makeTestCase(ITestCase* _testCase,
8114 std::string const& _className,
8115 std::string const& _name,
8116 std::string const& _descOrTags,
8117 SourceLineInfo const& _lineInfo)
8118 {
8119 bool isHidden(startsWith(_name, "./")); // Legacy support
8120
8121 // Parse out tags
8122 std::set<std::string> tags;
8123 std::string desc, tag;
8124 bool inTag = false;
8125 for (std::size_t i = 0; i < _descOrTags.size(); ++i)
8126 {
8127 char c = _descOrTags[i];
8128 if (!inTag)
8129 {
8130 if (c == '[')
8131 inTag = true;
8132 else
8133 desc += c;
8134 }
8135 else
8136 {
8137 if (c == ']')
8138 {
8139 TestCaseInfo::SpecialProperties prop = parseSpecialTag(tag);
8140 if (prop == TestCaseInfo::IsHidden)
8141 isHidden = true;
8142 else if (prop == TestCaseInfo::None)
8143 enforceNotReservedTag(tag, _lineInfo);
8144
8145 tags.insert(tag);
8146 tag.clear();
8147 inTag = false;
8148 }
8149 else
8150 tag += c;
8151 }
8152 }
8153 if (isHidden)
8154 {
8155 tags.insert("hide");
8156 tags.insert(".");
8157 }
8158
8159 TestCaseInfo info(_name, _className, desc, tags, _lineInfo);
8160 return TestCase(_testCase, info);
8161 }
8162
setTags(TestCaseInfo & testCaseInfo,std::set<std::string> const & tags)8163 void setTags(TestCaseInfo& testCaseInfo, std::set<std::string> const& tags)
8164 {
8165 testCaseInfo.tags = tags;
8166 testCaseInfo.lcaseTags.clear();
8167
8168 std::ostringstream oss;
8169 for (std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it)
8170 {
8171 oss << "[" << *it << "]";
8172 std::string lcaseTag = toLower(*it);
8173 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>(testCaseInfo.properties | parseSpecialTag(lcaseTag));
8174 testCaseInfo.lcaseTags.insert(lcaseTag);
8175 }
8176 testCaseInfo.tagsAsString = oss.str();
8177 }
8178
TestCaseInfo(std::string const & _name,std::string const & _className,std::string const & _description,std::set<std::string> const & _tags,SourceLineInfo const & _lineInfo)8179 TestCaseInfo::TestCaseInfo(std::string const& _name,
8180 std::string const& _className,
8181 std::string const& _description,
8182 std::set<std::string> const& _tags,
8183 SourceLineInfo const& _lineInfo)
8184 : name(_name),
8185 className(_className),
8186 description(_description),
8187 lineInfo(_lineInfo),
8188 properties(None)
8189 {
8190 setTags(*this, _tags);
8191 }
8192
TestCaseInfo(TestCaseInfo const & other)8193 TestCaseInfo::TestCaseInfo(TestCaseInfo const& other)
8194 : name(other.name),
8195 className(other.className),
8196 description(other.description),
8197 tags(other.tags),
8198 lcaseTags(other.lcaseTags),
8199 tagsAsString(other.tagsAsString),
8200 lineInfo(other.lineInfo),
8201 properties(other.properties)
8202 {
8203 }
8204
isHidden() const8205 bool TestCaseInfo::isHidden() const
8206 {
8207 return (properties & IsHidden) != 0;
8208 }
throws() const8209 bool TestCaseInfo::throws() const
8210 {
8211 return (properties & Throws) != 0;
8212 }
okToFail() const8213 bool TestCaseInfo::okToFail() const
8214 {
8215 return (properties & (ShouldFail | MayFail)) != 0;
8216 }
expectedToFail() const8217 bool TestCaseInfo::expectedToFail() const
8218 {
8219 return (properties & (ShouldFail)) != 0;
8220 }
8221
TestCase(ITestCase * testCase,TestCaseInfo const & info)8222 TestCase::TestCase(ITestCase* testCase, TestCaseInfo const& info) : TestCaseInfo(info), test(testCase) {}
8223
TestCase(TestCase const & other)8224 TestCase::TestCase(TestCase const& other)
8225 : TestCaseInfo(other),
8226 test(other.test)
8227 {
8228 }
8229
withName(std::string const & _newName) const8230 TestCase TestCase::withName(std::string const& _newName) const
8231 {
8232 TestCase other(*this);
8233 other.name = _newName;
8234 return other;
8235 }
8236
swap(TestCase & other)8237 void TestCase::swap(TestCase& other)
8238 {
8239 test.swap(other.test);
8240 name.swap(other.name);
8241 className.swap(other.className);
8242 description.swap(other.description);
8243 tags.swap(other.tags);
8244 lcaseTags.swap(other.lcaseTags);
8245 tagsAsString.swap(other.tagsAsString);
8246 std::swap(TestCaseInfo::properties, static_cast<TestCaseInfo&>(other).properties);
8247 std::swap(lineInfo, other.lineInfo);
8248 }
8249
invoke() const8250 void TestCase::invoke() const
8251 {
8252 test->invoke();
8253 }
8254
operator ==(TestCase const & other) const8255 bool TestCase::operator==(TestCase const& other) const
8256 {
8257 return test.get() == other.test.get() &&
8258 name == other.name &&
8259 className == other.className;
8260 }
8261
operator <(TestCase const & other) const8262 bool TestCase::operator<(TestCase const& other) const
8263 {
8264 return name < other.name;
8265 }
operator =(TestCase const & other)8266 TestCase& TestCase::operator=(TestCase const& other)
8267 {
8268 TestCase temp(other);
8269 swap(temp);
8270 return *this;
8271 }
8272
getTestCaseInfo() const8273 TestCaseInfo const& TestCase::getTestCaseInfo() const
8274 {
8275 return *this;
8276 }
8277
8278 } // end namespace Catch
8279
8280 // #included from: catch_version.hpp
8281 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
8282
8283 namespace Catch {
8284
Version(unsigned int _majorVersion,unsigned int _minorVersion,unsigned int _patchNumber,std::string const & _branchName,unsigned int _buildNumber)8285 Version::Version(unsigned int _majorVersion,
8286 unsigned int _minorVersion,
8287 unsigned int _patchNumber,
8288 std::string const& _branchName,
8289 unsigned int _buildNumber)
8290 : majorVersion(_majorVersion),
8291 minorVersion(_minorVersion),
8292 patchNumber(_patchNumber),
8293 branchName(_branchName),
8294 buildNumber(_buildNumber)
8295 {
8296 }
8297
operator <<(std::ostream & os,Version const & version)8298 std::ostream& operator<<(std::ostream& os, Version const& version)
8299 {
8300 os << version.majorVersion << "."
8301 << version.minorVersion << "."
8302 << version.patchNumber;
8303
8304 if (!version.branchName.empty())
8305 {
8306 os << "-" << version.branchName
8307 << "." << version.buildNumber;
8308 }
8309 return os;
8310 }
8311
8312 Version libraryVersion(1, 3, 2, "", 0);
8313 }
8314
8315 // #included from: catch_message.hpp
8316 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
8317
8318 namespace Catch {
8319
MessageInfo(std::string const & _macroName,SourceLineInfo const & _lineInfo,ResultWas::OfType _type)8320 MessageInfo::MessageInfo(std::string const& _macroName,
8321 SourceLineInfo const& _lineInfo,
8322 ResultWas::OfType _type)
8323 : macroName(_macroName),
8324 lineInfo(_lineInfo),
8325 type(_type),
8326 sequence(++globalCount)
8327 {
8328 }
8329
8330 // This may need protecting if threading support is added
8331 unsigned int MessageInfo::globalCount = 0;
8332
8333 ////////////////////////////////////////////////////////////////////////////
8334
ScopedMessage(MessageBuilder const & builder)8335 ScopedMessage::ScopedMessage(MessageBuilder const& builder)
8336 : m_info(builder.m_info)
8337 {
8338 m_info.message = builder.m_stream.str();
8339 getResultCapture().pushScopedMessage(m_info);
8340 }
ScopedMessage(ScopedMessage const & other)8341 ScopedMessage::ScopedMessage(ScopedMessage const& other)
8342 : m_info(other.m_info)
8343 {
8344 }
8345
~ScopedMessage()8346 ScopedMessage::~ScopedMessage()
8347 {
8348 getResultCapture().popScopedMessage(m_info);
8349 }
8350
8351 } // end namespace Catch
8352
8353 // #included from: catch_legacy_reporter_adapter.hpp
8354 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
8355
8356 // #included from: catch_legacy_reporter_adapter.h
8357 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
8358
8359 namespace Catch {
8360 // Deprecated
8361 struct IReporter : IShared
8362 {
8363 virtual ~IReporter();
8364
8365 virtual bool shouldRedirectStdout() const = 0;
8366
8367 virtual void StartTesting() = 0;
8368 virtual void EndTesting(Totals const& totals) = 0;
8369 virtual void StartGroup(std::string const& groupName) = 0;
8370 virtual void EndGroup(std::string const& groupName, Totals const& totals) = 0;
8371 virtual void StartTestCase(TestCaseInfo const& testInfo) = 0;
8372 virtual void EndTestCase(TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr) = 0;
8373 virtual void StartSection(std::string const& sectionName, std::string const& description) = 0;
8374 virtual void EndSection(std::string const& sectionName, Counts const& assertions) = 0;
8375 virtual void NoAssertionsInSection(std::string const& sectionName) = 0;
8376 virtual void NoAssertionsInTestCase(std::string const& testName) = 0;
8377 virtual void Aborted() = 0;
8378 virtual void Result(AssertionResult const& result) = 0;
8379 };
8380
8381 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
8382 {
8383 public:
8384 LegacyReporterAdapter(Ptr<IReporter> const& legacyReporter);
8385 virtual ~LegacyReporterAdapter();
8386
8387 virtual ReporterPreferences getPreferences() const;
8388 virtual void noMatchingTestCases(std::string const&);
8389 virtual void testRunStarting(TestRunInfo const&);
8390 virtual void testGroupStarting(GroupInfo const& groupInfo);
8391 virtual void testCaseStarting(TestCaseInfo const& testInfo);
8392 virtual void sectionStarting(SectionInfo const& sectionInfo);
8393 virtual void assertionStarting(AssertionInfo const&);
8394 virtual bool assertionEnded(AssertionStats const& assertionStats);
8395 virtual void sectionEnded(SectionStats const& sectionStats);
8396 virtual void testCaseEnded(TestCaseStats const& testCaseStats);
8397 virtual void testGroupEnded(TestGroupStats const& testGroupStats);
8398 virtual void testRunEnded(TestRunStats const& testRunStats);
8399 virtual void skipTest(TestCaseInfo const&);
8400
8401 private:
8402 Ptr<IReporter> m_legacyReporter;
8403 };
8404 }
8405
8406 namespace Catch {
LegacyReporterAdapter(Ptr<IReporter> const & legacyReporter)8407 LegacyReporterAdapter::LegacyReporterAdapter(Ptr<IReporter> const& legacyReporter)
8408 : m_legacyReporter(legacyReporter)
8409 {
8410 }
~LegacyReporterAdapter()8411 LegacyReporterAdapter::~LegacyReporterAdapter() {}
8412
getPreferences() const8413 ReporterPreferences LegacyReporterAdapter::getPreferences() const
8414 {
8415 ReporterPreferences prefs;
8416 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
8417 return prefs;
8418 }
8419
noMatchingTestCases(std::string const &)8420 void LegacyReporterAdapter::noMatchingTestCases(std::string const&) {}
testRunStarting(TestRunInfo const &)8421 void LegacyReporterAdapter::testRunStarting(TestRunInfo const&)
8422 {
8423 m_legacyReporter->StartTesting();
8424 }
testGroupStarting(GroupInfo const & groupInfo)8425 void LegacyReporterAdapter::testGroupStarting(GroupInfo const& groupInfo)
8426 {
8427 m_legacyReporter->StartGroup(groupInfo.name);
8428 }
testCaseStarting(TestCaseInfo const & testInfo)8429 void LegacyReporterAdapter::testCaseStarting(TestCaseInfo const& testInfo)
8430 {
8431 m_legacyReporter->StartTestCase(testInfo);
8432 }
sectionStarting(SectionInfo const & sectionInfo)8433 void LegacyReporterAdapter::sectionStarting(SectionInfo const& sectionInfo)
8434 {
8435 m_legacyReporter->StartSection(sectionInfo.name, sectionInfo.description);
8436 }
assertionStarting(AssertionInfo const &)8437 void LegacyReporterAdapter::assertionStarting(AssertionInfo const&)
8438 {
8439 // Not on legacy interface
8440 }
8441
assertionEnded(AssertionStats const & assertionStats)8442 bool LegacyReporterAdapter::assertionEnded(AssertionStats const& assertionStats)
8443 {
8444 if (assertionStats.assertionResult.getResultType() != ResultWas::Ok)
8445 {
8446 for (std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
8447 it != itEnd;
8448 ++it)
8449 {
8450 if (it->type == ResultWas::Info)
8451 {
8452 ResultBuilder rb(it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal);
8453 rb << it->message;
8454 rb.setResultType(ResultWas::Info);
8455 AssertionResult result = rb.build();
8456 m_legacyReporter->Result(result);
8457 }
8458 }
8459 }
8460 m_legacyReporter->Result(assertionStats.assertionResult);
8461 return true;
8462 }
sectionEnded(SectionStats const & sectionStats)8463 void LegacyReporterAdapter::sectionEnded(SectionStats const& sectionStats)
8464 {
8465 if (sectionStats.missingAssertions)
8466 m_legacyReporter->NoAssertionsInSection(sectionStats.sectionInfo.name);
8467 m_legacyReporter->EndSection(sectionStats.sectionInfo.name, sectionStats.assertions);
8468 }
testCaseEnded(TestCaseStats const & testCaseStats)8469 void LegacyReporterAdapter::testCaseEnded(TestCaseStats const& testCaseStats)
8470 {
8471 m_legacyReporter->EndTestCase(testCaseStats.testInfo,
8472 testCaseStats.totals,
8473 testCaseStats.stdOut,
8474 testCaseStats.stdErr);
8475 }
testGroupEnded(TestGroupStats const & testGroupStats)8476 void LegacyReporterAdapter::testGroupEnded(TestGroupStats const& testGroupStats)
8477 {
8478 if (testGroupStats.aborting)
8479 m_legacyReporter->Aborted();
8480 m_legacyReporter->EndGroup(testGroupStats.groupInfo.name, testGroupStats.totals);
8481 }
testRunEnded(TestRunStats const & testRunStats)8482 void LegacyReporterAdapter::testRunEnded(TestRunStats const& testRunStats)
8483 {
8484 m_legacyReporter->EndTesting(testRunStats.totals);
8485 }
skipTest(TestCaseInfo const &)8486 void LegacyReporterAdapter::skipTest(TestCaseInfo const&)
8487 {
8488 }
8489 }
8490
8491 // #included from: catch_timer.hpp
8492
8493 #ifdef __clang__
8494 #pragma clang diagnostic push
8495 #pragma clang diagnostic ignored "-Wc++11-long-long"
8496 #endif
8497
8498 #ifdef CATCH_PLATFORM_WINDOWS
8499 #include <windows.h>
8500 #else
8501 #include <sys/time.h>
8502 #endif
8503
8504 namespace Catch {
8505
8506 namespace {
8507 #ifdef CATCH_PLATFORM_WINDOWS
getCurrentTicks()8508 uint64_t getCurrentTicks()
8509 {
8510 static uint64_t hz = 0, hzo = 0;
8511 if (!hz)
8512 {
8513 QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&hz));
8514 QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&hzo));
8515 }
8516 uint64_t t;
8517 QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&t));
8518 return ((t - hzo) * 1000000) / hz;
8519 }
8520 #else
8521 uint64_t getCurrentTicks()
8522 {
8523 timeval t;
8524 gettimeofday(&t, CATCH_NULL);
8525 return static_cast<uint64_t>(t.tv_sec) * 1000000ull + static_cast<uint64_t>(t.tv_usec);
8526 }
8527 #endif
8528 }
8529
start()8530 void Timer::start()
8531 {
8532 m_ticks = getCurrentTicks();
8533 }
getElapsedMicroseconds() const8534 unsigned int Timer::getElapsedMicroseconds() const
8535 {
8536 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
8537 }
getElapsedMilliseconds() const8538 unsigned int Timer::getElapsedMilliseconds() const
8539 {
8540 return static_cast<unsigned int>(getElapsedMicroseconds() / 1000);
8541 }
getElapsedSeconds() const8542 double Timer::getElapsedSeconds() const
8543 {
8544 return getElapsedMicroseconds() / 1000000.0;
8545 }
8546
8547 } // namespace Catch
8548
8549 #ifdef __clang__
8550 #pragma clang diagnostic pop
8551 #endif
8552 // #included from: catch_common.hpp
8553 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
8554
8555 namespace Catch {
8556
startsWith(std::string const & s,std::string const & prefix)8557 bool startsWith(std::string const& s, std::string const& prefix)
8558 {
8559 return s.size() >= prefix.size() && s.substr(0, prefix.size()) == prefix;
8560 }
endsWith(std::string const & s,std::string const & suffix)8561 bool endsWith(std::string const& s, std::string const& suffix)
8562 {
8563 return s.size() >= suffix.size() && s.substr(s.size() - suffix.size(), suffix.size()) == suffix;
8564 }
contains(std::string const & s,std::string const & infix)8565 bool contains(std::string const& s, std::string const& infix)
8566 {
8567 return s.find(infix) != std::string::npos;
8568 }
toLowerInPlace(std::string & s)8569 void toLowerInPlace(std::string& s)
8570 {
8571 std::transform(s.begin(), s.end(), s.begin(), ::tolower);
8572 }
toLower(std::string const & s)8573 std::string toLower(std::string const& s)
8574 {
8575 std::string lc = s;
8576 toLowerInPlace(lc);
8577 return lc;
8578 }
trim(std::string const & str)8579 std::string trim(std::string const& str)
8580 {
8581 static char const* whitespaceChars = "\n\r\t ";
8582 std::string::size_type start = str.find_first_not_of(whitespaceChars);
8583 std::string::size_type end = str.find_last_not_of(whitespaceChars);
8584
8585 return start != std::string::npos ? str.substr(start, 1 + end - start) : "";
8586 }
8587
replaceInPlace(std::string & str,std::string const & replaceThis,std::string const & withThis)8588 bool replaceInPlace(std::string& str, std::string const& replaceThis, std::string const& withThis)
8589 {
8590 bool replaced = false;
8591 std::size_t i = str.find(replaceThis);
8592 while (i != std::string::npos)
8593 {
8594 replaced = true;
8595 str = str.substr(0, i) + withThis + str.substr(i + replaceThis.size());
8596 if (i < str.size() - withThis.size())
8597 i = str.find(replaceThis, i + withThis.size());
8598 else
8599 i = std::string::npos;
8600 }
8601 return replaced;
8602 }
8603
pluralise(std::size_t count,std::string const & label)8604 pluralise::pluralise(std::size_t count, std::string const& label)
8605 : m_count(count),
8606 m_label(label)
8607 {
8608 }
8609
operator <<(std::ostream & os,pluralise const & pluraliser)8610 std::ostream& operator<<(std::ostream& os, pluralise const& pluraliser)
8611 {
8612 os << pluraliser.m_count << " " << pluraliser.m_label;
8613 if (pluraliser.m_count != 1)
8614 os << "s";
8615 return os;
8616 }
8617
SourceLineInfo()8618 SourceLineInfo::SourceLineInfo() : line(0) {}
SourceLineInfo(char const * _file,std::size_t _line)8619 SourceLineInfo::SourceLineInfo(char const* _file, std::size_t _line)
8620 : file(_file),
8621 line(_line)
8622 {
8623 }
SourceLineInfo(SourceLineInfo const & other)8624 SourceLineInfo::SourceLineInfo(SourceLineInfo const& other)
8625 : file(other.file),
8626 line(other.line)
8627 {
8628 }
empty() const8629 bool SourceLineInfo::empty() const
8630 {
8631 return file.empty();
8632 }
operator ==(SourceLineInfo const & other) const8633 bool SourceLineInfo::operator==(SourceLineInfo const& other) const
8634 {
8635 return line == other.line && file == other.file;
8636 }
operator <(SourceLineInfo const & other) const8637 bool SourceLineInfo::operator<(SourceLineInfo const& other) const
8638 {
8639 return line < other.line || (line == other.line && file < other.file);
8640 }
8641
seedRng(IConfig const & config)8642 void seedRng(IConfig const& config)
8643 {
8644 if (config.rngSeed() != 0)
8645 std::srand(config.rngSeed());
8646 }
rngSeed()8647 unsigned int rngSeed()
8648 {
8649 return getCurrentContext().getConfig()->rngSeed();
8650 }
8651
operator <<(std::ostream & os,SourceLineInfo const & info)8652 std::ostream& operator<<(std::ostream& os, SourceLineInfo const& info)
8653 {
8654 #ifndef __GNUG__
8655 os << info.file << "(" << info.line << ")";
8656 #else
8657 os << info.file << ":" << info.line;
8658 #endif
8659 return os;
8660 }
8661
throwLogicError(std::string const & message,SourceLineInfo const & locationInfo)8662 void throwLogicError(std::string const& message, SourceLineInfo const& locationInfo)
8663 {
8664 std::ostringstream oss;
8665 oss << locationInfo << ": Internal Catch error: '" << message << "'";
8666 if (alwaysTrue())
8667 throw std::logic_error(oss.str());
8668 }
8669 }
8670
8671 // #included from: catch_section.hpp
8672 #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
8673
8674 namespace Catch {
8675
SectionInfo(SourceLineInfo const & _lineInfo,std::string const & _name,std::string const & _description)8676 SectionInfo::SectionInfo(SourceLineInfo const& _lineInfo,
8677 std::string const& _name,
8678 std::string const& _description)
8679 : name(_name),
8680 description(_description),
8681 lineInfo(_lineInfo)
8682 {
8683 }
8684
Section(SectionInfo const & info)8685 Section::Section(SectionInfo const& info)
8686 : m_info(info),
8687 m_sectionIncluded(getResultCapture().sectionStarted(m_info, m_assertions))
8688 {
8689 m_timer.start();
8690 }
8691
~Section()8692 Section::~Section()
8693 {
8694 if (m_sectionIncluded)
8695 {
8696 SectionEndInfo endInfo(m_info, m_assertions, m_timer.getElapsedSeconds());
8697 if (std::uncaught_exception())
8698 getResultCapture().sectionEndedEarly(endInfo);
8699 else
8700 getResultCapture().sectionEnded(endInfo);
8701 }
8702 }
8703
8704 // This indicates whether the section should be executed or not
operator bool() const8705 Section::operator bool() const
8706 {
8707 return m_sectionIncluded;
8708 }
8709
8710 } // end namespace Catch
8711
8712 // #included from: catch_debugger.hpp
8713 #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
8714
8715 #include <iostream>
8716
8717 #ifdef CATCH_PLATFORM_MAC
8718
8719 #include <assert.h>
8720 #include <stdbool.h>
8721 #include <sys/sysctl.h>
8722 #include <sys/types.h>
8723 #include <unistd.h>
8724
8725 namespace Catch {
8726
8727 // The following function is taken directly from the following technical note:
8728 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
8729
8730 // Returns true if the current process is being debugged (either
8731 // running under the debugger or has a debugger attached post facto).
isDebuggerActive()8732 bool isDebuggerActive()
8733 {
8734
8735 int mib[4];
8736 struct kinfo_proc info;
8737 size_t size;
8738
8739 // Initialize the flags so that, if sysctl fails for some bizarre
8740 // reason, we get a predictable result.
8741
8742 info.kp_proc.p_flag = 0;
8743
8744 // Initialize mib, which tells sysctl the info we want, in this case
8745 // we're looking for information about a specific process ID.
8746
8747 mib[0] = CTL_KERN;
8748 mib[1] = KERN_PROC;
8749 mib[2] = KERN_PROC_PID;
8750 mib[3] = getpid();
8751
8752 // Call sysctl.
8753
8754 size = sizeof(info);
8755 if (sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0)
8756 {
8757 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n"
8758 << std::endl;
8759 return false;
8760 }
8761
8762 // We're being debugged if the P_TRACED flag is set.
8763
8764 return ((info.kp_proc.p_flag & P_TRACED) != 0);
8765 }
8766 } // namespace Catch
8767
8768 #elif defined(_MSC_VER)
8769 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8770 namespace Catch {
isDebuggerActive()8771 bool isDebuggerActive()
8772 {
8773 return IsDebuggerPresent() != 0;
8774 }
8775 }
8776 #elif defined(__MINGW32__)
8777 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8778 namespace Catch {
isDebuggerActive()8779 bool isDebuggerActive()
8780 {
8781 return IsDebuggerPresent() != 0;
8782 }
8783 }
8784 #else
8785 namespace Catch {
isDebuggerActive()8786 inline bool isDebuggerActive() { return false; }
8787 }
8788 #endif // Platform
8789
8790 #ifdef CATCH_PLATFORM_WINDOWS
8791 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char*);
8792 namespace Catch {
writeToDebugConsole(std::string const & text)8793 void writeToDebugConsole(std::string const& text)
8794 {
8795 ::OutputDebugStringA(text.c_str());
8796 }
8797 }
8798 #else
8799 namespace Catch {
writeToDebugConsole(std::string const & text)8800 void writeToDebugConsole(std::string const& text)
8801 {
8802 // !TBD: Need a version for Mac/ XCode and other IDEs
8803 Catch::cout() << text;
8804 }
8805 }
8806 #endif // Platform
8807
8808 // #included from: catch_tostring.hpp
8809 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
8810
8811 namespace Catch {
8812
8813 namespace Detail {
8814
8815 const std::string unprintableString = "{?}";
8816
8817 namespace {
8818 const int hexThreshold = 255;
8819
8820 struct Endianness
8821 {
8822 enum Arch
8823 {
8824 Big,
8825 Little
8826 };
8827
whichCatch::Detail::__anon5602dd960811::Endianness8828 static Arch which()
8829 {
8830 union _
8831 {
8832 int asInt;
8833 char asChar[sizeof(int)];
8834 } u;
8835
8836 u.asInt = 1;
8837 return (u.asChar[sizeof(int) - 1] == 1) ? Big : Little;
8838 }
8839 };
8840 }
8841
rawMemoryToString(const void * object,std::size_t size)8842 std::string rawMemoryToString(const void* object, std::size_t size)
8843 {
8844 // Reverse order for little endian architectures
8845 int i = 0, end = static_cast<int>(size), inc = 1;
8846 if (Endianness::which() == Endianness::Little)
8847 {
8848 i = end - 1;
8849 end = inc = -1;
8850 }
8851
8852 unsigned char const* bytes = static_cast<unsigned char const*>(object);
8853 std::ostringstream os;
8854 os << "0x" << std::setfill('0') << std::hex;
8855 for (; i != end; i += inc)
8856 os << std::setw(2) << static_cast<unsigned>(bytes[i]);
8857 return os.str();
8858 }
8859 }
8860
toString(std::string const & value)8861 std::string toString(std::string const& value)
8862 {
8863 std::string s = value;
8864 if (getCurrentContext().getConfig()->showInvisibles())
8865 {
8866 for (size_t i = 0; i < s.size(); ++i)
8867 {
8868 std::string subs;
8869 switch (s[i])
8870 {
8871 case '\n':
8872 subs = "\\n";
8873 break;
8874 case '\t':
8875 subs = "\\t";
8876 break;
8877 default:
8878 break;
8879 }
8880 if (!subs.empty())
8881 {
8882 s = s.substr(0, i) + subs + s.substr(i + 1);
8883 ++i;
8884 }
8885 }
8886 }
8887 return "\"" + s + "\"";
8888 }
toString(std::wstring const & value)8889 std::string toString(std::wstring const& value)
8890 {
8891
8892 std::string s;
8893 s.reserve(value.size());
8894 for (size_t i = 0; i < value.size(); ++i)
8895 s += value[i] <= 0xff ? static_cast<char>(value[i]) : '?';
8896 return Catch::toString(s);
8897 }
8898
toString(const char * const value)8899 std::string toString(const char* const value)
8900 {
8901 return value ? Catch::toString(std::string(value)) : std::string("{null string}");
8902 }
8903
toString(char * const value)8904 std::string toString(char* const value)
8905 {
8906 return Catch::toString(static_cast<const char*>(value));
8907 }
8908
toString(const wchar_t * const value)8909 std::string toString(const wchar_t* const value)
8910 {
8911 return value ? Catch::toString(std::wstring(value)) : std::string("{null string}");
8912 }
8913
toString(wchar_t * const value)8914 std::string toString(wchar_t* const value)
8915 {
8916 return Catch::toString(static_cast<const wchar_t*>(value));
8917 }
8918
toString(int value)8919 std::string toString(int value)
8920 {
8921 std::ostringstream oss;
8922 oss << value;
8923 if (value > Detail::hexThreshold)
8924 oss << " (0x" << std::hex << value << ")";
8925 return oss.str();
8926 }
8927
toString(unsigned long value)8928 std::string toString(unsigned long value)
8929 {
8930 std::ostringstream oss;
8931 oss << value;
8932 if (value > Detail::hexThreshold)
8933 oss << " (0x" << std::hex << value << ")";
8934 return oss.str();
8935 }
8936
toString(unsigned int value)8937 std::string toString(unsigned int value)
8938 {
8939 return Catch::toString(static_cast<unsigned long>(value));
8940 }
8941
8942 template <typename T>
fpToString(T value,int precision)8943 std::string fpToString(T value, int precision)
8944 {
8945 std::ostringstream oss;
8946 oss << std::setprecision(precision)
8947 << std::fixed
8948 << value;
8949 std::string d = oss.str();
8950 std::size_t i = d.find_last_not_of('0');
8951 if (i != std::string::npos && i != d.size() - 1)
8952 {
8953 if (d[i] == '.')
8954 i++;
8955 d = d.substr(0, i + 1);
8956 }
8957 return d;
8958 }
8959
toString(const double value)8960 std::string toString(const double value)
8961 {
8962 return fpToString(value, 10);
8963 }
toString(const float value)8964 std::string toString(const float value)
8965 {
8966 return fpToString(value, 5) + "f";
8967 }
8968
toString(bool value)8969 std::string toString(bool value)
8970 {
8971 return value ? "true" : "false";
8972 }
8973
toString(char value)8974 std::string toString(char value)
8975 {
8976 return value < ' '
8977 ? toString(static_cast<unsigned int>(value))
8978 : Detail::makeString(value);
8979 }
8980
toString(signed char value)8981 std::string toString(signed char value)
8982 {
8983 return toString(static_cast<char>(value));
8984 }
8985
toString(unsigned char value)8986 std::string toString(unsigned char value)
8987 {
8988 return toString(static_cast<char>(value));
8989 }
8990
8991 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
toString(long long value)8992 std::string toString(long long value)
8993 {
8994 std::ostringstream oss;
8995 oss << value;
8996 if (value > Detail::hexThreshold)
8997 oss << " (0x" << std::hex << value << ")";
8998 return oss.str();
8999 }
toString(unsigned long long value)9000 std::string toString(unsigned long long value)
9001 {
9002 std::ostringstream oss;
9003 oss << value;
9004 if (value > Detail::hexThreshold)
9005 oss << " (0x" << std::hex << value << ")";
9006 return oss.str();
9007 }
9008 #endif
9009
9010 #ifdef CATCH_CONFIG_CPP11_NULLPTR
toString(std::nullptr_t)9011 std::string toString(std::nullptr_t)
9012 {
9013 return "nullptr";
9014 }
9015 #endif
9016
9017 #ifdef __OBJC__
toString(NSString const * const & nsstring)9018 std::string toString(NSString const* const& nsstring)
9019 {
9020 if (!nsstring)
9021 return "nil";
9022 return "@" + toString([nsstring UTF8String]);
9023 }
toString(NSString * CATCH_ARC_STRONG const & nsstring)9024 std::string toString(NSString* CATCH_ARC_STRONG const& nsstring)
9025 {
9026 if (!nsstring)
9027 return "nil";
9028 return "@" + toString([nsstring UTF8String]);
9029 }
toString(NSObject * const & nsObject)9030 std::string toString(NSObject* const& nsObject)
9031 {
9032 return toString([nsObject description]);
9033 }
9034 #endif
9035
9036 } // end namespace Catch
9037
9038 // #included from: catch_result_builder.hpp
9039 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
9040
9041 namespace Catch {
9042
capturedExpressionWithSecondArgument(std::string const & capturedExpression,std::string const & secondArg)9043 std::string capturedExpressionWithSecondArgument(std::string const& capturedExpression, std::string const& secondArg)
9044 {
9045 return secondArg.empty() || secondArg == "\"\""
9046 ? capturedExpression
9047 : capturedExpression + ", " + secondArg;
9048 }
ResultBuilder(char const * macroName,SourceLineInfo const & lineInfo,char const * capturedExpression,ResultDisposition::Flags resultDisposition,char const * secondArg)9049 ResultBuilder::ResultBuilder(char const* macroName,
9050 SourceLineInfo const& lineInfo,
9051 char const* capturedExpression,
9052 ResultDisposition::Flags resultDisposition,
9053 char const* secondArg)
9054 : m_assertionInfo(macroName, lineInfo, capturedExpressionWithSecondArgument(capturedExpression, secondArg), resultDisposition),
9055 m_shouldDebugBreak(false),
9056 m_shouldThrow(false)
9057 {
9058 }
9059
setResultType(ResultWas::OfType result)9060 ResultBuilder& ResultBuilder::setResultType(ResultWas::OfType result)
9061 {
9062 m_data.resultType = result;
9063 return *this;
9064 }
setResultType(bool result)9065 ResultBuilder& ResultBuilder::setResultType(bool result)
9066 {
9067 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
9068 return *this;
9069 }
setLhs(std::string const & lhs)9070 ResultBuilder& ResultBuilder::setLhs(std::string const& lhs)
9071 {
9072 m_exprComponents.lhs = lhs;
9073 return *this;
9074 }
setRhs(std::string const & rhs)9075 ResultBuilder& ResultBuilder::setRhs(std::string const& rhs)
9076 {
9077 m_exprComponents.rhs = rhs;
9078 return *this;
9079 }
setOp(std::string const & op)9080 ResultBuilder& ResultBuilder::setOp(std::string const& op)
9081 {
9082 m_exprComponents.op = op;
9083 return *this;
9084 }
9085
endExpression()9086 void ResultBuilder::endExpression()
9087 {
9088 m_exprComponents.testFalse = isFalseTest(m_assertionInfo.resultDisposition);
9089 captureExpression();
9090 }
9091
useActiveException(ResultDisposition::Flags resultDisposition)9092 void ResultBuilder::useActiveException(ResultDisposition::Flags resultDisposition)
9093 {
9094 m_assertionInfo.resultDisposition = resultDisposition;
9095 m_stream.oss << Catch::translateActiveException();
9096 captureResult(ResultWas::ThrewException);
9097 }
9098
captureResult(ResultWas::OfType resultType)9099 void ResultBuilder::captureResult(ResultWas::OfType resultType)
9100 {
9101 setResultType(resultType);
9102 captureExpression();
9103 }
captureExpectedException(std::string const & expectedMessage)9104 void ResultBuilder::captureExpectedException(std::string const& expectedMessage)
9105 {
9106 if (expectedMessage.empty())
9107 captureExpectedException(Matchers::Impl::Generic::AllOf<std::string>());
9108 else
9109 captureExpectedException(Matchers::Equals(expectedMessage));
9110 }
9111
captureExpectedException(Matchers::Impl::Matcher<std::string> const & matcher)9112 void ResultBuilder::captureExpectedException(Matchers::Impl::Matcher<std::string> const& matcher)
9113 {
9114
9115 assert(m_exprComponents.testFalse == false);
9116 AssertionResultData data = m_data;
9117 data.resultType = ResultWas::Ok;
9118 data.reconstructedExpression = m_assertionInfo.capturedExpression;
9119
9120 std::string actualMessage = Catch::translateActiveException();
9121 if (!matcher.match(actualMessage))
9122 {
9123 data.resultType = ResultWas::ExpressionFailed;
9124 data.reconstructedExpression = actualMessage;
9125 }
9126 AssertionResult result(m_assertionInfo, data);
9127 handleResult(result);
9128 }
9129
captureExpression()9130 void ResultBuilder::captureExpression()
9131 {
9132 AssertionResult result = build();
9133 handleResult(result);
9134 }
handleResult(AssertionResult const & result)9135 void ResultBuilder::handleResult(AssertionResult const& result)
9136 {
9137 getResultCapture().assertionEnded(result);
9138
9139 if (!result.isOk())
9140 {
9141 if (getCurrentContext().getConfig()->shouldDebugBreak())
9142 m_shouldDebugBreak = true;
9143 if (getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal))
9144 m_shouldThrow = true;
9145 }
9146 }
react()9147 void ResultBuilder::react()
9148 {
9149 if (m_shouldThrow)
9150 throw Catch::TestFailureException();
9151 }
9152
shouldDebugBreak() const9153 bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
allowThrows() const9154