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