blob: 89800f17aeb272c9a3fb9c3f9255fb2cb267dca9 [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001// This file has been merged from multiple headers. Please don't edit it directly
2
3#ifndef TWOBLUECUBES_CATCH_HPP_INCLUDED
4#define TWOBLUECUBES_CATCH_HPP_INCLUDED
5/*
6 * catch.hpp
7 * Catch
8 *
9 * Created by Phil on 22/10/2010.
10 * Copyright 2010 Two Blue Cubes Ltd
11 *
12 * Distributed under the Boost Software License, Version 1.0. (See accompanying
13 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
14 *
15 */
16
17/* TBD:
18
19 Next:
20
21 Later:
Phil Nash62a5ddc2011-06-29 19:25:14 +010022 Finish command line parser (list as xml)
Phil Nash89d1e6c2011-05-24 08:23:02 +010023 Tags?
24 Finish macros, listed here, later (just CHECK_NOFAIL now)
25 */
26#define TWOBLUECUBES_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010027// #included from: internal/catch_hub.h
28
29/*
30 * catch_hub.h
31 * Catch
32 *
33 * Created by Phil on 31/12/2010.
34 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
35 *
36 * Distributed under the Boost Software License, Version 1.0. (See accompanying
37 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
38 *
39 */
40#define TWOBLUECUBES_CATCH_HUB_H_INCLUDED
41
42// #included from: catch_interfaces_reporter.h
43
44/*
45 * catch_interfaces_reporter.h
46 * Test
47 *
48 * Created by Phil on 31/12/2010.
49 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
50 *
51 * Distributed under the Boost Software License, Version 1.0. (See accompanying
52 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
53 *
54 */
55
56#define TWOBLUECUBES_CATCH_IREPORTERREGISTRY_INCLUDED
57
58// #included from: catch_common.h
59
60/*
61 * catch_common.h
62 * Catch
63 *
64 * Created by Phil on 29/10/2010.
65 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
66 *
67 * Distributed under the Boost Software License, Version 1.0. (See accompanying
68 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
69 *
70 */
71
72#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
73
74#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
75#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
76#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
77
78#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
79#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
80
81#ifdef __GNUC__
82#define ATTRIBUTE_NORETURN __attribute__ ((noreturn))
83#else
84#define ATTRIBUTE_NORETURN
85#endif
86
87#include <sstream>
88#include <stdexcept>
89#include <algorithm>
90
91namespace Catch
92{
93 class NonCopyable
94 {
95 NonCopyable( const NonCopyable& );
96 void operator = ( const NonCopyable& );
97 protected:
98 NonCopyable(){}
99 };
100
101 typedef char NoType;
102 typedef int YesType;
103
104 // create a T for use in sizeof expressions
105 template<typename T> T Synth();
106
107 template<typename ContainerT>
108 inline void deleteAll( ContainerT& container )
109 {
110 typename ContainerT::const_iterator it = container.begin();
111 typename ContainerT::const_iterator itEnd = container.end();
112 for(; it != itEnd; ++it )
113 {
114 delete *it;
115 }
116 }
117 template<typename AssociativeContainerT>
118 inline void deleteAllValues( AssociativeContainerT& container )
119 {
120 typename AssociativeContainerT::const_iterator it = container.begin();
121 typename AssociativeContainerT::const_iterator itEnd = container.end();
122 for(; it != itEnd; ++it )
123 {
124 delete it->second;
125 }
126 }
127
128 template<typename ContainerT, typename Function>
129 inline void forEach( ContainerT& container, Function function )
130 {
131 std::for_each( container.begin(), container.end(), function );
132 }
133
134 template<typename ContainerT, typename Function>
135 inline void forEach( const ContainerT& container, Function function )
136 {
137 std::for_each( container.begin(), container.end(), function );
138 }
139
140 ATTRIBUTE_NORETURN
141 inline void throwLogicError( const std::string& message, const std::string& file, long line )
142 {
143 std::ostringstream oss;
144 oss << "Internal Catch error: '" << message << "' at: " << file << "(" << line << ")";
145 throw std::logic_error( oss.str() );
146 }
147}
148
149#define CATCH_INTERNAL_ERROR( msg ) throwLogicError( msg, __FILE__, __LINE__ );
150
151
152
153#include <string>
154#include <ostream>
155#include <map>
156
157namespace Catch
158{
159 ///////////////////////////////////////////////////////////////////////////
160 struct IReporterConfig
161 {
162 virtual ~IReporterConfig
163 ()
164 {}
165
166 virtual std::ostream& stream
167 () const = 0;
168
169 virtual bool includeSuccessfulResults
170 () const = 0;
171
172 virtual std::string getName
173 () const = 0;
174 };
175
176 class TestCaseInfo;
177 class ResultInfo;
178
179 ///////////////////////////////////////////////////////////////////////////
180 struct IReporter : NonCopyable
181 {
182 virtual ~IReporter
183 (){}
184
185 virtual void StartTesting
186 () = 0;
187
188 virtual void EndTesting
189 ( std::size_t succeeded,
190 std::size_t failed
191 ) = 0;
192
193 virtual void StartGroup
194 ( const std::string& groupName
195 ) = 0;
196
197 virtual void EndGroup
198 ( const std::string& groupName,
199 std::size_t succeeded,
200 std::size_t failed
201 ) = 0;
202
203 virtual void StartSection
204 ( const std::string& sectionName,
205 const std::string description
206 ) = 0;
207
208 virtual void EndSection
209 ( const std::string& sectionName,
210 std::size_t succeeded,
211 std::size_t failed
212 ) = 0;
213
214 virtual void StartTestCase
215 ( const TestCaseInfo& testInfo
216 ) = 0;
217
218 virtual void EndTestCase
219 ( const TestCaseInfo& testInfo,
220 std::size_t succeeded,
221 std::size_t failed,
222 const std::string& stdOut,
223 const std::string& stdErr
224 ) = 0;
225
226 virtual void Result
227 ( const ResultInfo& result
228 ) = 0;
229 };
230
231 ///////////////////////////////////////////////////////////////////////////
232 struct IReporterFactory
233 {
234 virtual ~IReporterFactory
235 (){}
236
237 virtual IReporter* create
238 ( const IReporterConfig& config
239 ) const = 0;
240
241 virtual std::string getDescription
242 () const = 0;
243 };
244
245 ///////////////////////////////////////////////////////////////////////////
246 struct IReporterRegistry
247 {
248 typedef std::map<std::string, IReporterFactory*> FactoryMap;
249
250 virtual ~IReporterRegistry
251 (){}
252
253 virtual IReporter* create
254 ( const std::string& name,
255 const IReporterConfig& config
256 ) const = 0;
257
258 virtual void registerReporter
259 ( const std::string& name,
260 IReporterFactory* factory
261 ) = 0;
262
263 virtual const FactoryMap& getFactories
264 () const = 0;
265
266 };
267
268 ///////////////////////////////////////////////////////////////////////////
269 inline std::string trim( const std::string& str )
270 {
271 std::string::size_type start = str.find_first_not_of( "\n\r\t " );
272 std::string::size_type end = str.find_last_not_of( "\n\r\t " );
273
274 return start < end ? str.substr( start, 1+end-start ) : "";
275 }
276
277
278}
279
280
281#include <memory>
282#include <vector>
283#include <stdlib.h>
284
285namespace Catch
286{
287 class TestCaseInfo;
288 struct IResultCapture;
289 struct ITestCaseRegistry;
290 struct IRunner;
291 struct IExceptionTranslatorRegistry;
292 class GeneratorsForTest;
293
294 class StreamBufBase : public std::streambuf
295 {
296 };
297
298 class Hub
299 {
300 Hub();
301
302 static Hub& me();
303
304 Hub( const Hub& );
305 void operator=( const Hub& );
306
307 public:
308
309 static void setRunner
310 ( IRunner* runner
311 );
312
313 static void setResultCapture
314 ( IResultCapture* resultCapture
315 );
316
317 static IResultCapture& getResultCapture
318 ();
319
320 static IReporterRegistry& getReporterRegistry
321 ();
322
323 static ITestCaseRegistry& getTestCaseRegistry
324 ();
325
326 static IExceptionTranslatorRegistry& getExceptionTranslatorRegistry
327 ();
328
329 static std::streambuf* createStreamBuf
330 ( const std::string& streamName
331 );
332
333 static IRunner& getRunner
334 ();
335
336 static size_t getGeneratorIndex
337 ( const std::string& fileInfo,
338 size_t totalSize
339 );
340
341 static bool advanceGeneratorsForCurrentTest
342 ();
343
344 private:
345 GeneratorsForTest* findGeneratorsForCurrentTest
346 ();
347
348 GeneratorsForTest& getGeneratorsForCurrentTest
349 ();
350
351 std::auto_ptr<IReporterRegistry> m_reporterRegistry;
352 std::auto_ptr<ITestCaseRegistry> m_testCaseRegistry;
353 std::auto_ptr<IExceptionTranslatorRegistry> m_exceptionTranslatorRegistry;
354 IRunner* m_runner;
355 IResultCapture* m_resultCapture;
356 std::map<std::string, GeneratorsForTest*> m_generatorsByTestName;
357 };
358}
359
360// #included from: internal/catch_test_registry.hpp
361
362/*
363 * catch_test_registry.hpp
364 * Catch
365 *
366 * Created by Phil on 18/10/2010.
367 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
368 *
369 * Distributed under the Boost Software License, Version 1.0. (See accompanying
370 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
371 *
372 */
373#define TWOBLUECUBES_CATCH_REGISTRY_HPP_INCLUDED
374
375// #included from: catch_interfaces_testcase.h
376
377/*
378 * catch_interfaces_testcase.h
379 * Catch
380 *
381 * Created by Phil on 07/01/2011.
382 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
383 *
384 * Distributed under the Boost Software License, Version 1.0. (See accompanying
385 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
386 *
387 */
388
389#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
390
391#include <vector>
392
393namespace Catch
394{
395 struct ITestCase
396 {
397 virtual ~ITestCase
398 ()
399 {}
400
401 virtual void invoke
402 () const = 0;
403
404 virtual ITestCase* clone
405 () const = 0;
406
407 virtual bool operator ==
408 ( const ITestCase& other
409 ) const = 0;
410
411 virtual bool operator <
412 ( const ITestCase& other
413 ) const = 0;
414 };
415
416 class TestCaseInfo;
417
418 struct ITestCaseRegistry
419 {
420 virtual ~ITestCaseRegistry
421 ()
422 {}
423
424 virtual void registerTest
425 ( const TestCaseInfo& testInfo
426 ) = 0;
427
428 virtual const std::vector<TestCaseInfo>& getAllTests
429 () const = 0;
430
431 virtual std::vector<TestCaseInfo> getMatchingTestCases
432 ( const std::string& rawTestSpec
433 ) = 0;
434 };
435}
436
437
438
439
440namespace Catch
441{
442
443template<typename C>
444struct MethodTestCase : ITestCase
445{
446 ///////////////////////////////////////////////////////////////////////////
447 MethodTestCase
448 (
449 void (C::*method)()
450 )
451 : m_method( method )
452 {}
453
454 ///////////////////////////////////////////////////////////////////////////
455 virtual void invoke
456 ()
457 const
458 {
459 C obj;
460 (obj.*m_method)();
461 }
462
463 ///////////////////////////////////////////////////////////////////////////
464 virtual ITestCase* clone
465 ()
466 const
467 {
468 return new MethodTestCase<C>( m_method );
469 }
470
471 ///////////////////////////////////////////////////////////////////////////
472 virtual bool operator ==
473 (
474 const ITestCase& other
475 )
476 const
477 {
478 const MethodTestCase* mtOther = dynamic_cast<const MethodTestCase*>( &other );
479 return mtOther && m_method == mtOther->m_method;
480 }
481
482 ///////////////////////////////////////////////////////////////////////////
483 virtual bool operator <
484 (
485 const ITestCase& other
486 )
487 const
488 {
489 const MethodTestCase* mtOther = dynamic_cast<const MethodTestCase*>( &other );
490 return mtOther && &m_method < &mtOther->m_method;
491 }
492
493private:
494 void (C::*m_method)();
495};
496
497typedef void(*TestFunction)();
498
499struct AutoReg
500{
501 AutoReg
502 ( TestFunction function,
503 const char* name,
504 const char* description,
505 const char* filename,
506 std::size_t line
507 );
508
509 ///////////////////////////////////////////////////////////////////////////
510 template<typename C>
511 AutoReg
512 (
513 void (C::*method)(),
514 const char* name,
515 const char* description,
516 const char* filename,
517 std::size_t line
518 )
519 {
520 registerTestCase( new MethodTestCase<C>( method ), name, description, filename, line );
521 }
522
523 ///////////////////////////////////////////////////////////////////////////
524 void registerTestCase
525 (
526 ITestCase* testCase,
527 const char* name,
528 const char* description,
529 const char* filename,
530 std::size_t line
531 );
532
533 ~AutoReg
534 ();
535
536private:
537 AutoReg
538 ( const AutoReg& );
539
540 void operator=
541 ( const AutoReg& );
542};
543
544} // end namespace Catch
545
546///////////////////////////////////////////////////////////////////////////////
547#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
548 static void INTERNAL_CATCH_UNIQUE_NAME( catch_internal_TestFunction )(); \
549 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_TestFunction ), Name, Desc, __FILE__, __LINE__ ); }\
550 static void INTERNAL_CATCH_UNIQUE_NAME( catch_internal_TestFunction )()
551
552///////////////////////////////////////////////////////////////////////////////
553#define INTERNAL_CATCH_TESTCASE_NORETURN( Name, Desc ) \
554 static void INTERNAL_CATCH_UNIQUE_NAME( catch_internal_TestFunction )() ATTRIBUTE_NORETURN; \
555 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_TestFunction ), Name, Desc, __FILE__, __LINE__ ); }\
556 static void INTERNAL_CATCH_UNIQUE_NAME( catch_internal_TestFunction )()
557
558///////////////////////////////////////////////////////////////////////////////
559#define CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
560 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, Name, Desc, __FILE__, __LINE__ ); }
561
562///////////////////////////////////////////////////////////////////////////////
563#define TEST_CASE_METHOD( ClassName, TestName, Desc )\
564 struct INTERNAL_CATCH_UNIQUE_NAME( Catch_FixtureWrapper ) : ClassName \
565 { \
566 void test(); \
567 }; \
568 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( Catch_FixtureWrapper )::test, TestName, Desc, __FILE__, __LINE__ ); } \
569 void INTERNAL_CATCH_UNIQUE_NAME( Catch_FixtureWrapper )::test()
570
571// #included from: internal/catch_capture.hpp
572
573/*
574 * catch_capture.hpp
575 * Catch
576 *
577 * Created by Phil on 18/10/2010.
578 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
579 *
580 * Distributed under the Boost Software License, Version 1.0. (See accompanying
581 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
582 *
583 */
584#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
585
586// #included from: catch_resultinfo.hpp
587
588/*
589 * catch_resultinfo.hpp
590 * Catch
591 *
592 * Created by Phil on 28/10/2010.
593 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
594 *
595 * Distributed under the Boost Software License, Version 1.0. (See accompanying
596 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
597 *
598 */
599#define TWOBLUECUBES_CATCH_RESULT_INFO_HPP_INCLUDED
600
601#include <string>
602// #included from: catch_result_type.h
603
604/*
605 * catch_result_type.h
606 * Catch
607 *
608 * Created by Phil on 07/01/2011.
609 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
610 *
611 * Distributed under the Boost Software License, Version 1.0. (See accompanying
612 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
613 *
614 */
615
616#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
617
618namespace Catch
619{
620
621struct ResultWas{ enum OfType
622 {
623 Unknown = -1,
624 Ok = 0,
625 Info = 1,
626 Warning = 2,
627
628 FailureBit = 0x10,
629
630 ExpressionFailed = FailureBit | 1,
631 ExplicitFailure = FailureBit | 2,
632
633 Exception = 0x100 | FailureBit,
634
635 ThrewException = Exception | 1,
636 DidntThrowException = Exception | 2
637
638 }; };
639
640 struct ResultAction
641 {
642 enum Value
643 {
644 None,
645 Failed = 1, // Failure - but no debug break if Debug bit not set
646 DebugFailed = 3 // Indicates that the debugger should break, if possible
647 };
648 };
649
650}
651
652
653
654namespace Catch
655{
656 class ResultInfo
657 {
658 public:
659
660 ///////////////////////////////////////////////////////////////////////////
661 ResultInfo
662 ()
663 : m_line( 0 ),
664 m_result( ResultWas::Unknown ),
665 m_isNot( false )
666 {}
667
668 ///////////////////////////////////////////////////////////////////////////
669 ResultInfo
670 (
671 const char* expr,
672 ResultWas::OfType result,
673 bool isNot,
674 const char* filename,
675 std::size_t line,
676 const char* macroName,
677 const char* message
678 )
679 : m_macroName( macroName ),
680 m_filename( filename ),
681 m_line( line ),
682 m_expr( expr ),
683 m_op( isNotExpression( expr ) ? "!" : "" ),
684 m_message( message ),
685 m_result( result ),
686 m_isNot( isNot )
687 {
688 if( isNot )
689 m_expr = "!" + m_expr;
690 }
691
692 ///////////////////////////////////////////////////////////////////////////
693 bool ok
694 ()
695 const
696 {
697 return ( m_result & ResultWas::FailureBit ) != ResultWas::FailureBit;
698 }
699
700 ///////////////////////////////////////////////////////////////////////////
701 ResultWas::OfType getResultType
702 ()
703 const
704 {
705 return m_result;
706 }
707
708 ///////////////////////////////////////////////////////////////////////////
709 bool hasExpression
710 ()
711 const
712 {
713 return !m_expr.empty();
714 }
715
716 ///////////////////////////////////////////////////////////////////////////
717 bool hasMessage
718 ()
719 const
720 {
721 return !m_message.empty();
722 }
723
724 ///////////////////////////////////////////////////////////////////////////
725 std::string getExpression
726 ()
727 const
728 {
729 return m_expr;
730 }
731
732 ///////////////////////////////////////////////////////////////////////////
733 std::string getExpandedExpression
734 ()
735 const
736 {
737 return hasExpression() ? getExpandedExpressionInternal() : "";
738 }
739
740 ///////////////////////////////////////////////////////////////////////////
741 std::string getMessage
742 ()
743 const
744 {
745 return m_message;
746 }
747
748 ///////////////////////////////////////////////////////////////////////////
749 std::string getFilename
750 ()
751 const
752 {
753 return m_filename;
754 }
755
756 ///////////////////////////////////////////////////////////////////////////
757 std::size_t getLine
758 ()
759 const
760 {
761 return m_line;
762 }
763
764 ///////////////////////////////////////////////////////////////////////////
765 std::string getTestMacroName
766 ()
767 const
768 {
769 return m_macroName;
770 }
771
772 protected:
773
774 ///////////////////////////////////////////////////////////////////////////
775 std::string getExpandedExpressionInternal
776 ()
777 const
778 {
779 if( m_op == "" || m_isNot )
780 return m_lhs.empty() ? m_expr : m_op + m_lhs;
781 else if( m_op != "!" )
782 return m_lhs + " " + m_op + " " + m_rhs;
783 else
784 return "{can't expand - use " + m_macroName + "_NOT( " + m_expr.substr(1) + " ) instead of " + m_macroName + "( " + m_expr + " ) for better diagnostics}";
785 }
786
787 ///////////////////////////////////////////////////////////////////////////
788 bool isNotExpression
789 (
790 const char* expr
791 )
792 {
793 return expr && expr[0] == '!';
794 }
795
796 protected:
797 std::string m_macroName;
798 std::string m_filename;
799 std::size_t m_line;
800 std::string m_expr, m_lhs, m_rhs, m_op;
801 std::string m_message;
802 ResultWas::OfType m_result;
803 bool m_isNot;
804 };
805
806} // end namespace Catch
807
808
809// #included from: catch_interfaces_capture.h
810
811/*
812 * catch_interfaces_capture.h
813 * Catch
814 *
815 * Created by Phil on 07/01/2011.
816 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
817 *
818 * Distributed under the Boost Software License, Version 1.0. (See accompanying
819 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
820 *
821 */
822#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
823
824#include <string>
825
826namespace Catch
827{
828 class TestCaseInfo;
829 class ScopedInfo;
830 class MutableResultInfo;
831
832 struct IResultCapture
833 {
834 virtual ~IResultCapture
835 ()
836 {}
837
838 virtual void testEnded
839 ( const ResultInfo& result
840 ) = 0;
841 virtual bool sectionStarted
842 ( const std::string& name,
843 const std::string& description,
844 const std::string& filename,
845 std::size_t line,
846 std::size_t& successes,
847 std::size_t& failures
848 ) = 0;
849 virtual void sectionEnded
850 ( const std::string& name,
851 std::size_t successes,
852 std::size_t failures
853 ) = 0;
854 virtual void pushScopedInfo
855 ( ScopedInfo* scopedInfo
856 ) = 0;
857 virtual void popScopedInfo
858 ( ScopedInfo* scopedInfo
859 ) = 0;
860 virtual bool shouldDebugBreak
861 () const = 0;
862
863 virtual ResultAction::Value acceptResult
864 ( bool result
865 ) = 0;
866 virtual ResultAction::Value acceptResult
867 ( ResultWas::OfType result
868 ) = 0;
869 virtual ResultAction::Value acceptExpression
870 ( const MutableResultInfo& resultInfo
871 ) = 0;
872 virtual void acceptMessage
873 ( const std::string& msg
874 ) = 0;
875
876 virtual std::string getCurrentTestName
877 () const = 0;
878
879 };
880}
881
882// #included from: catch_debugger.hpp
883
884/*
885 * catch_debugger.hpp
886 * Catch
887 *
888 * Created by Phil on 27/12/2010.
889 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
890 *
891 * Distributed under the Boost Software License, Version 1.0. (See accompanying
892 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
893 *
894 * Provides a BreakIntoDebugger() macro for Windows and Mac (so far)
895 */
896
897#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
898
899#include <iostream>
900
901#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
902#define CATCH_PLATFORM_MAC
903#elif defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
904#define CATCH_PLATFORM_WINDOWS
905#endif
906
907#ifdef CATCH_PLATFORM_MAC
908
909 #include <assert.h>
910 #include <stdbool.h>
911 #include <sys/types.h>
912 #include <unistd.h>
913 #include <sys/sysctl.h>
914
915 namespace Catch
916 {
917 // The following function is taken directly from the following technical note:
918 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
919
920 inline bool isDebuggerActive()
921 // Returns true if the current process is being debugged (either
922 // running under the debugger or has a debugger attached post facto).
923 {
924 int junk;
925 int mib[4];
926 struct kinfo_proc info;
927 size_t size;
928
929 // Initialize the flags so that, if sysctl fails for some bizarre
930 // reason, we get a predictable result.
931
932 info.kp_proc.p_flag = 0;
933
934 // Initialize mib, which tells sysctl the info we want, in this case
935 // we're looking for information about a specific process ID.
936
937 mib[0] = CTL_KERN;
938 mib[1] = KERN_PROC;
939 mib[2] = KERN_PROC_PID;
940 mib[3] = getpid();
941
942 // Call sysctl.
943
944 size = sizeof(info);
945 junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
946 assert(junk == 0);
947
948 // We're being debugged if the P_TRACED flag is set.
949
950 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
951 }
952 }
953
954 // The following code snippet taken from:
955 // http://cocoawithlove.com/2008/03/break-into-debugger.html
956 #ifdef DEBUG
957 #if defined(__ppc64__) || defined(__ppc__)
958 #define BreakIntoDebugger() \
959 if( Catch::isDebuggerActive() ) \
960 { \
961 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
962 : : : "memory","r0","r3","r4" ); \
963 }
964 #else
965 #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
966 #endif
967 #else
968 inline void BreakIntoDebugger(){}
969 #endif
970
Phil Nashd6566f92011-07-04 09:14:15 +0100971#elif defined(_MSC_VER)
Phil Nash89d1e6c2011-05-24 08:23:02 +0100972 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
973 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
974 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
975 inline bool isDebuggerActive()
976 {
977 return IsDebuggerPresent() != 0;
978 }
979#else
980 inline void BreakIntoDebugger(){}
981 inline bool isDebuggerActive() { return false; }
982#endif
983
984inline void writeToDebugConsole( const std::string& text )
985{
986#ifdef CATCH_PLATFORM_WINDOWS
987 ::OutputDebugStringA( text.c_str() );
988#else
989 // !TBD: Need a version for Mac/ XCode and other IDEs
990 std::cout << text;
991#endif
992}
993
994// #included from: catch_evaluate.hpp
995
996/*
997 * catch_evaluate.hpp
998 * Catch
999 *
1000 * Created by Phil on 04/03/2011.
1001 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
1002 *
1003 * Distributed under the Boost Software License, Version 1.0. (See accompanying
1004 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1005 *
1006 */
1007
1008#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
1009
1010namespace Catch
1011{
1012namespace Internal
1013{
1014 enum Operator
1015 {
1016 IsEqualTo,
1017 IsNotEqualTo,
1018 IsLessThan,
1019 IsGreaterThan,
1020 IsLessThanOrEqualTo,
1021 IsGreaterThanOrEqualTo
1022 };
1023
1024 template<Operator Op>
1025 struct OperatorTraits{ static const char* getName(){ return "*error - unknown operator*"; } };
1026
1027 template<>
1028 struct OperatorTraits<IsEqualTo>{ static const char* getName(){ return "=="; } };
1029
1030 template<>
1031 struct OperatorTraits<IsNotEqualTo>{ static const char* getName(){ return "!="; } };
1032
1033 template<>
1034 struct OperatorTraits<IsLessThan>{ static const char* getName(){ return "<"; } };
1035
1036 template<>
1037 struct OperatorTraits<IsGreaterThan>{ static const char* getName(){ return ">"; } };
1038
1039 template<>
1040 struct OperatorTraits<IsLessThanOrEqualTo>{ static const char* getName(){ return "<="; } };
1041
1042 template<>
1043 struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
1044
1045 // So the compare overloads can be operator agnostic we convey the operator as a template
1046 // enum, which is used to specialise an Evaluator for doing the comparison.
1047 template<typename T1, typename T2, Operator Op>
1048 class Evaluator{};
1049
1050 template<typename T1, typename T2>
1051 struct Evaluator<T1, T2, IsEqualTo>
1052 {
1053 static bool evaluate( const T1& lhs, const T2& rhs)
1054 {
1055 return const_cast<T1&>( lhs ) == const_cast<T2&>( rhs );
1056 }
1057 };
1058 template<typename T1, typename T2>
1059 struct Evaluator<T1, T2, IsNotEqualTo>
1060 {
1061 static bool evaluate( const T1& lhs, const T2& rhs )
1062 {
1063 return const_cast<T1&>( lhs ) != const_cast<T2&>( rhs );
1064 }
1065 };
1066 template<typename T1, typename T2>
1067 struct Evaluator<T1, T2, IsLessThan>
1068 {
1069 static bool evaluate( const T1& lhs, const T2& rhs )
1070 {
1071 return const_cast<T1&>( lhs ) < const_cast<T2&>( rhs );
1072 }
1073 };
1074 template<typename T1, typename T2>
1075 struct Evaluator<T1, T2, IsGreaterThan>
1076 {
1077 static bool evaluate( const T1& lhs, const T2& rhs )
1078 {
1079 return const_cast<T1&>( lhs ) > const_cast<T2&>( rhs );
1080 }
1081 };
1082 template<typename T1, typename T2>
1083 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo>
1084 {
1085 static bool evaluate( const T1& lhs, const T2& rhs )
1086 {
1087 return const_cast<T1&>( lhs ) >= const_cast<T2&>( rhs );
1088 }
1089 };
1090 template<typename T1, typename T2>
1091 struct Evaluator<T1, T2, IsLessThanOrEqualTo>
1092 {
1093 static bool evaluate( const T1& lhs, const T2& rhs )
1094 {
1095 return const_cast<T1&>( lhs ) <= const_cast<T2&>( rhs );
1096 }
1097 };
1098
1099 template<Operator Op, typename T1, typename T2>
1100 bool applyEvaluator( const T1& lhs, const T2& rhs )
1101 {
1102 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1103 }
1104
1105 // "base" overload
1106 template<Operator Op, typename T1, typename T2>
1107 bool compare( const T1& lhs, const T2& rhs )
1108 {
1109 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1110 }
1111
1112 // unsigned X to int
1113 template<Operator Op> bool compare( unsigned int lhs, int rhs )
1114 {
1115 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1116 }
1117 template<Operator Op> bool compare( unsigned long lhs, int rhs )
1118 {
1119 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1120 }
1121 template<Operator Op> bool compare( unsigned char lhs, int rhs )
1122 {
1123 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1124 }
1125
1126 // unsigned X to long
1127 template<Operator Op> bool compare( unsigned int lhs, long rhs )
1128 {
1129 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1130 }
1131 template<Operator Op> bool compare( unsigned long lhs, long rhs )
1132 {
1133 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1134 }
1135 template<Operator Op> bool compare( unsigned char lhs, long rhs )
1136 {
1137 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1138 }
1139
1140 // int to unsigned X
1141 template<Operator Op> bool compare( int lhs, unsigned int rhs )
1142 {
1143 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1144 }
1145 template<Operator Op> bool compare( int lhs, unsigned long rhs )
1146 {
1147 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1148 }
1149 template<Operator Op> bool compare( int lhs, unsigned char rhs )
1150 {
1151 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1152 }
1153
1154 // long to unsigned X
1155 template<Operator Op> bool compare( long lhs, unsigned int rhs )
1156 {
1157 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ) );
1158 }
1159 template<Operator Op> bool compare( long lhs, unsigned long rhs )
1160 {
1161 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ) );
1162 }
1163 template<Operator Op> bool compare( long lhs, unsigned char rhs )
1164 {
1165 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ) );
1166 }
1167
1168 template<Operator Op, typename T>
1169 bool compare( long lhs, const T* rhs )
1170 {
1171 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( NULL ), rhs );
1172
1173 }
1174
1175 template<Operator Op, typename T>
1176 bool compare( long lhs, T* rhs )
1177 {
1178 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1179
1180 }
1181
1182} // end of namespace Internal
1183} // end of namespace Catch
1184
1185#include <sstream>
1186
1187namespace Catch
1188{
1189namespace Detail
1190{
1191 // The following code, contributed by Sam Partington, allows us to choose an implementation
1192 // of toString() depending on whether a << overload is available
1193
1194 struct NonStreamable
1195 {
1196 // allow construction from anything...
1197 template<typename Anything>
1198 NonStreamable(Anything)
1199 {}
1200 };
1201
1202 // a local operator<< which may be called if there isn't a better one elsewhere...
1203 inline NonStreamable operator << ( std::ostream&, const NonStreamable& ns )
1204 {
1205 return ns;
1206 }
1207
1208 template<typename T>
1209 struct IsStreamable
1210 {
1211 static NoType Deduce( const NonStreamable& );
1212 static YesType Deduce( std::ostream& );
1213
1214 enum
1215 {
1216 value = sizeof( Deduce( Synth<std::ostream&>() << Synth<const T&>() ) )
1217 == sizeof( YesType )
1218 };
1219 };
1220
1221 // << is available, so use it with ostringstream to make the string
1222 template<typename T, bool streamable>
1223 struct StringMaker
1224 {
1225 ///////////////////////////////////////////////////////////////////////
1226 static std::string apply
1227 (
1228 const T& value
1229 )
1230 {
1231 std::ostringstream oss;
1232 oss << value;
1233 return oss.str();
1234 }
1235 };
1236
1237 // << not available - use a default string
1238 template<typename T>
1239 struct StringMaker<T, false>
1240 {
1241 ///////////////////////////////////////////////////////////////////////
1242 static std::string apply
1243 (
1244 const T&
1245 )
1246 {
1247 return "{?}";
1248 }
1249 };
1250
1251}// end namespace Detail
1252
1253///////////////////////////////////////////////////////////////////////////////
1254template<typename T>
1255std::string toString
1256(
1257 const T& value
1258)
1259{
1260 return Detail::StringMaker<T, Detail::IsStreamable<T>::value>::apply( value );
1261}
1262
1263// Shortcut overloads
1264
1265///////////////////////////////////////////////////////////////////////////////
1266inline std::string toString
1267(
1268 const std::string& value
1269)
1270{
1271 return "\"" + value + "\"";
1272}
1273
1274///////////////////////////////////////////////////////////////////////////////
1275inline std::string toString
1276(
1277 const std::wstring& value
1278)
1279{
1280 std::ostringstream oss;
1281 oss << "\"";
1282 for(size_t i = 0; i < value.size(); ++i )
1283 oss << static_cast<char>( value[i] <= 0xff ? value[i] : '?');
1284 oss << "\"";
1285 return oss.str();
1286}
1287
1288///////////////////////////////////////////////////////////////////////////////
1289inline std::string toString
1290(
1291 const char* const value
1292)
1293{
1294 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
1295}
1296
1297///////////////////////////////////////////////////////////////////////////////
1298inline std::string toString
1299(
1300 char* const value
1301)
1302{
1303 return Catch::toString( static_cast<const char* const>( value ) );
1304}
1305
1306///////////////////////////////////////////////////////////////////////////////
1307inline std::string toString
1308(
1309 int value
1310)
1311{
1312 std::ostringstream oss;
1313 oss << value;
1314 return oss.str();
1315}
1316
1317///////////////////////////////////////////////////////////////////////////////
1318inline std::string toString
1319(
1320 unsigned int value
1321)
1322{
1323 std::ostringstream oss;
1324 if( value > 8192 )
1325 oss << "0x" << std::hex << value;
1326 else
1327 oss << value;
1328 return oss.str();
1329}
1330
1331///////////////////////////////////////////////////////////////////////////////
1332inline std::string toString
1333(
1334 unsigned long value
1335)
1336{
1337 std::ostringstream oss;
1338 if( value > 8192 )
1339 oss << "0x" << std::hex << value;
1340 else
1341 oss << value;
1342 return oss.str();
1343}
1344
1345///////////////////////////////////////////////////////////////////////////////
1346inline std::string toString
1347(
1348 const double value
1349)
1350{
1351 std::ostringstream oss;
1352 oss << value;
1353 return oss.str();
1354}
1355
1356///////////////////////////////////////////////////////////////////////////////
1357inline std::string toString
1358(
1359 bool value
1360)
1361{
1362 return value ? "true" : "false";
1363}
1364
1365///////////////////////////////////////////////////////////////////////////////
1366inline std::string toString
1367(
1368 void* p
1369)
1370{
1371 if( !p )
1372 return INTERNAL_CATCH_STRINGIFY( NULL );
1373 std::ostringstream oss;
1374 oss << p;
1375 return oss.str();
1376}
1377
1378///////////////////////////////////////////////////////////////////////////////
1379template<typename T>
1380inline std::string toString
1381(
1382 T* p
1383)
1384{
1385 return Catch::toString( static_cast<void*>( p ) );
1386}
1387
1388///////////////////////////////////////////////////////////////////////////////
1389template<typename T>
1390inline std::string toString
1391(
1392 const T* p
1393)
1394{
1395 return Catch::toString( static_cast<void*>( const_cast<T*>( p ) ) );
1396}
1397
1398struct TestFailureException
1399{
1400};
1401struct DummyExceptionType_DontUse
1402{
1403};
1404struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1405
1406class MutableResultInfo : public ResultInfo
1407{
1408public:
1409
1410 ///////////////////////////////////////////////////////////////////////////
1411 MutableResultInfo
1412 ()
1413 {}
1414
1415 ///////////////////////////////////////////////////////////////////////////
1416 MutableResultInfo
1417 (
1418 const char* expr,
1419 bool isNot,
1420 const char* filename,
1421 std::size_t line,
1422 const char* macroName,
1423 const char* message = ""
1424 )
1425 : ResultInfo( expr, ResultWas::Unknown, isNot, filename, line, macroName, message )
1426 {
1427 }
1428
1429 ///////////////////////////////////////////////////////////////////////////
1430 void setResultType
1431 (
1432 ResultWas::OfType result
1433 )
1434 {
1435 // Flip bool results if isNot is set
1436 if( m_isNot && result == ResultWas::Ok )
1437 m_result = ResultWas::ExpressionFailed;
1438 else if( m_isNot && result == ResultWas::ExpressionFailed )
1439 m_result = ResultWas::Ok;
1440 else
1441 m_result = result;
1442 }
1443
1444 ///////////////////////////////////////////////////////////////////////////
1445 void setMessage
1446 (
1447 const std::string& message
1448 )
1449 {
1450 m_message = message;
1451 }
1452
1453 ///////////////////////////////////////////////////////////////////////////
1454 void setFileAndLine
1455 (
1456 const std::string& filename,
1457 std::size_t line
1458 )
1459 {
1460 m_filename = filename;
1461 m_line = line;
1462 }
1463
1464 ///////////////////////////////////////////////////////////////////////////
1465 template<typename RhsT>
1466 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator ||
1467 (
1468 const RhsT&
1469 );
1470
1471 ///////////////////////////////////////////////////////////////////////////
1472 template<typename RhsT>
1473 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator &&
1474 (
1475 const RhsT&
1476 );
1477
1478private:
1479 friend class ResultBuilder;
1480 template<typename T> friend class Expression;
1481
1482 template<typename T> friend class PtrExpression;
1483
1484 ///////////////////////////////////////////////////////////////////////////
1485 MutableResultInfo& captureBoolExpression
1486 (
1487 bool result
1488 )
1489 {
1490 m_lhs = Catch::toString( result );
1491 m_op = m_isNot ? "!" : "";
1492 setResultType( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
1493 return *this;
1494 }
1495
1496 ///////////////////////////////////////////////////////////////////////////
1497 template<Internal::Operator Op, typename T1, typename T2>
1498 MutableResultInfo& captureExpression
1499 (
1500 const T1& lhs,
1501 const T2& rhs
1502 )
1503 {
1504 setResultType( Internal::compare<Op>( lhs, rhs ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
1505 m_lhs = Catch::toString( lhs );
1506 m_rhs = Catch::toString( rhs );
1507 m_op = Internal::OperatorTraits<Op>::getName();
1508 return *this;
1509 }
1510
Phil Nash4021d652011-07-15 08:12:10 +01001511 ///////////////////////////////////////////////////////////////////////////
1512 template<Internal::Operator Op, typename T>
1513 MutableResultInfo& captureExpression
1514 (
1515 const T* lhs,
1516 int rhs
1517 )
1518 {
1519 return captureExpression<Op>( lhs, reinterpret_cast<const T*>( rhs ) );
1520 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001521};
1522
1523template<typename T>
1524class Expression
1525{
1526 void operator = ( const Expression& );
1527
1528public:
1529 ///////////////////////////////////////////////////////////////////////////
1530 Expression
1531 (
1532 MutableResultInfo& result,
Phil Nash98a21bc2011-09-19 18:23:07 +01001533 T lhs
Phil Nash89d1e6c2011-05-24 08:23:02 +01001534 )
1535 : m_result( result ),
1536 m_lhs( lhs )
1537 {
1538 }
1539
1540 ///////////////////////////////////////////////////////////////////////////
1541 template<typename RhsT>
1542 MutableResultInfo& operator ==
1543 (
1544 const RhsT& rhs
1545 )
1546 {
1547 return m_result.captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1548 }
1549
1550 ///////////////////////////////////////////////////////////////////////////
1551 template<typename RhsT>
1552 MutableResultInfo& operator !=
1553 (
1554 const RhsT& rhs
1555 )
1556 {
1557 return m_result.captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1558 }
1559
1560 ///////////////////////////////////////////////////////////////////////////
1561 template<typename RhsT>
1562 MutableResultInfo& operator <
1563 (
1564 const RhsT& rhs
1565 )
1566 {
1567 return m_result.captureExpression<Internal::IsLessThan>( m_lhs, rhs );
1568 }
1569
1570 ///////////////////////////////////////////////////////////////////////////
1571 template<typename RhsT>
1572 MutableResultInfo& operator >
1573 (
1574 const RhsT& rhs
1575 )
1576 {
1577 return m_result.captureExpression<Internal::IsGreaterThan>( m_lhs, rhs );
1578 }
1579
1580 ///////////////////////////////////////////////////////////////////////////
1581 template<typename RhsT>
1582 MutableResultInfo& operator <=
1583 (
1584 const RhsT& rhs
1585 )
1586 {
1587 return m_result.captureExpression<Internal::IsLessThanOrEqualTo>( m_lhs, rhs );
1588 }
1589
1590 ///////////////////////////////////////////////////////////////////////////
1591 template<typename RhsT>
1592 MutableResultInfo& operator >=
1593 (
1594 const RhsT& rhs
1595 )
1596 {
1597 return m_result.captureExpression<Internal::IsGreaterThanOrEqualTo>( m_lhs, rhs );
1598 }
1599
1600 ///////////////////////////////////////////////////////////////////////////
Phil Nash22545402011-08-09 18:41:01 +01001601 MutableResultInfo& operator ==
1602 (
1603 bool rhs
1604 )
1605 {
1606 return m_result.captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1607 }
1608
1609 ///////////////////////////////////////////////////////////////////////////
1610 MutableResultInfo& operator !=
1611 (
1612 bool rhs
1613 )
1614 {
1615 return m_result.captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1616 }
1617
1618 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01001619 operator MutableResultInfo&
1620 ()
1621 {
1622 return m_result.captureBoolExpression( m_lhs );
1623 }
1624
1625 ///////////////////////////////////////////////////////////////////////////
1626 template<typename RhsT>
1627 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator +
1628 (
1629 const RhsT&
1630 );
1631
1632 ///////////////////////////////////////////////////////////////////////////
1633 template<typename RhsT>
1634 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator -
1635 (
1636 const RhsT&
1637 );
1638
1639private:
1640 MutableResultInfo& m_result;
Phil Nash98a21bc2011-09-19 18:23:07 +01001641 T m_lhs;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001642};
1643
1644template<typename LhsT>
1645class PtrExpression
1646{
1647public:
1648
1649 ///////////////////////////////////////////////////////////////////////////
1650 PtrExpression
1651 (
1652 MutableResultInfo& result,
1653 const LhsT* lhs
1654 )
1655 : m_result( &result ),
1656 m_lhs( lhs )
1657 {}
1658
1659 ///////////////////////////////////////////////////////////////////////////
1660 template<typename RhsT>
1661 MutableResultInfo& operator ==
1662 (
1663 const RhsT* rhs
1664 )
1665 {
1666 return m_result->captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1667 }
1668
1669 ///////////////////////////////////////////////////////////////////////////
1670 // This catches NULL
1671 MutableResultInfo& operator ==
1672 (
1673 LhsT* rhs
1674 )
1675 {
1676 return m_result->captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1677 }
1678
1679 ///////////////////////////////////////////////////////////////////////////
1680 template<typename RhsT>
1681 MutableResultInfo& operator !=
1682 (
1683 const RhsT* rhs
1684 )
1685 {
1686 return m_result->captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1687 }
1688
1689 ///////////////////////////////////////////////////////////////////////////
1690 // This catches NULL
1691 MutableResultInfo& operator !=
1692 (
1693 LhsT* rhs
1694 )
1695 {
1696 return m_result->captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1697 }
1698
1699 ///////////////////////////////////////////////////////////////////////////
1700 operator MutableResultInfo&
1701 ()
1702 {
1703 return m_result->captureBoolExpression( m_lhs );
1704 }
1705
1706
1707private:
1708 MutableResultInfo* m_result;
1709 const LhsT* m_lhs;
1710};
1711
1712class ResultBuilder
1713{
1714public:
1715
1716 ///////////////////////////////////////////////////////////////////////////
1717 ResultBuilder
1718 (
1719 const char* filename,
1720 std::size_t line,
1721 const char* macroName,
1722 const char* expr = "",
1723 bool isNot = false
1724 )
1725 : m_result( expr, isNot, filename, line, macroName )
1726 {}
1727
1728 ///////////////////////////////////////////////////////////////////////////
1729 template<typename T>
Phil Nash98a21bc2011-09-19 18:23:07 +01001730 Expression<const T&> operator->*
Phil Nash89d1e6c2011-05-24 08:23:02 +01001731 (
1732 const T & operand
1733 )
1734 {
Phil Nash98a21bc2011-09-19 18:23:07 +01001735 Expression<const T&> expr( m_result, operand );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001736
1737 return expr;
1738 }
1739
1740 ///////////////////////////////////////////////////////////////////////////
Phil Nash62a5ddc2011-06-29 19:25:14 +01001741 Expression<const char*> operator->*
1742 (
Phil Nash4021d652011-07-15 08:12:10 +01001743 const char* const& operand
Phil Nash62a5ddc2011-06-29 19:25:14 +01001744 )
1745 {
1746 Expression<const char*> expr( m_result, operand );
1747
1748 return expr;
1749 }
1750
1751 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01001752 template<typename T>
1753 PtrExpression<T> operator->*
1754 (
1755 const T* operand
1756 )
1757 {
1758 PtrExpression<T> expr( m_result, operand );
1759
1760 return expr;
1761 }
1762
1763 ///////////////////////////////////////////////////////////////////////////
1764 template<typename T>
1765 PtrExpression<T> operator->*
1766 (
1767 T* operand
1768 )
1769 {
1770 PtrExpression<T> expr( m_result, operand );
1771
1772 return expr;
1773 }
1774
1775 ///////////////////////////////////////////////////////////////////////////
Phil Nash22545402011-08-09 18:41:01 +01001776 Expression<bool> operator->*
1777 (
1778 bool value
1779 )
1780 {
1781 Expression<bool> expr( m_result, value );
1782 return expr;
1783 }
1784
1785 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01001786 template<typename T>
1787 ResultBuilder& operator <<
1788 (
1789 const T & value
1790 )
1791 {
1792 m_messageStream << Catch::toString( value );
1793 return *this;
1794 }
1795
1796 ///////////////////////////////////////////////////////////////////////////
1797 ResultBuilder& setResultType
1798 (
1799 ResultWas::OfType resultType
1800 )
1801 {
1802 m_result.setResultType( resultType );
1803 return *this;
1804 }
1805
1806 ///////////////////////////////////////////////////////////////////////////
1807 operator MutableResultInfo&
1808 ()
1809 {
1810 m_result.setMessage( m_messageStream.str() );
1811 return m_result;
1812 }
1813
1814private:
1815 MutableResultInfo m_result;
1816 std::ostringstream m_messageStream;
1817
1818};
1819
1820class ScopedInfo
1821{
1822public:
1823 ///////////////////////////////////////////////////////////////////////////
1824 ScopedInfo
1825 ()
1826 {
1827 Hub::getResultCapture().pushScopedInfo( this );
1828 }
1829
1830 ///////////////////////////////////////////////////////////////////////////
1831 ~ScopedInfo
1832 ()
1833 {
1834 Hub::getResultCapture().popScopedInfo( this );
1835 }
1836
1837 ///////////////////////////////////////////////////////////////////////////
1838 ScopedInfo& operator <<
1839 (
1840 const char* str
1841 )
1842 {
1843 m_oss << str;
1844 return *this;
1845 }
1846
1847 ///////////////////////////////////////////////////////////////////////////
1848 std::string getInfo
1849 ()
1850 const
1851 {
1852 return m_oss.str();
1853 }
1854
1855private:
1856 std::ostringstream m_oss;
1857};
1858
1859///////////////////////////////////////////////////////////////////////////////
1860// This is just here to avoid compiler warnings with macro constants
1861inline bool isTrue
1862(
1863 bool value
1864)
1865{
1866 return value;
1867}
1868
1869} // end namespace Catch
1870
1871///////////////////////////////////////////////////////////////////////////////
1872#define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure ) \
Phil Nash3c20a752011-06-23 08:23:33 +01001873 if( Catch::ResultAction::Value internal_catch_action = Catch::Hub::getResultCapture().acceptExpression( expr ) ) \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001874 { \
Phil Nash3c20a752011-06-23 08:23:33 +01001875 if( internal_catch_action == Catch::ResultAction::DebugFailed ) BreakIntoDebugger(); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001876 if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \
1877 }
1878
1879///////////////////////////////////////////////////////////////////////////////
1880#define INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ) \
1881 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr, isNot )->*expr ), stopOnFailure ); \
Phil Nash3c20a752011-06-23 08:23:33 +01001882 if( Catch::isTrue( false ) ){ bool internal_catch_dummyResult = ( expr ); Catch::isTrue( internal_catch_dummyResult ); }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001883
1884///////////////////////////////////////////////////////////////////////////////
1885#define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \
1886 try \
1887 { \
1888 expr; \
1889 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure ); \
1890 } \
Phil Nash3c20a752011-06-23 08:23:33 +01001891 catch( std::exception& internal_catch_exception ) \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001892 { \
Phil Nash3c20a752011-06-23 08:23:33 +01001893 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << internal_catch_exception.what() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001894 } \
1895 catch( ... ) \
1896 { \
1897 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \
1898 }
1899
1900///////////////////////////////////////////////////////////////////////////////
1901#define INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
1902 try \
1903 { \
1904 expr; \
1905 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure ); \
1906 } \
1907 catch( Catch::TestFailureException& ) \
1908 { \
1909 throw; \
1910 } \
1911 catch( exceptionType ) \
1912 { \
1913 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure ); \
1914 }
1915
1916///////////////////////////////////////////////////////////////////////////////
1917#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, stopOnFailure, macroName ) \
1918 INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
1919 catch( ... ) \
1920 { \
1921 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \
1922 }
1923
1924///////////////////////////////////////////////////////////////////////////////
1925#define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \
1926 Catch::Hub::getResultCapture().acceptExpression( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName ) << reason ).setResultType( resultType ) );
1927
1928///////////////////////////////////////////////////////////////////////////////
1929#define INTERNAL_CATCH_SCOPED_INFO( log ) \
1930 Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
1931 INTERNAL_CATCH_UNIQUE_NAME( info ) << log
1932
1933// #included from: internal/catch_section.hpp
1934
1935/*
1936 * catch_section.hpp
1937 * Catch
1938 *
1939 * Created by Phil on 03/11/2010.
1940 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
1941 *
1942 * Distributed under the Boost Software License, Version 1.0. (See accompanying
1943 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1944 *
1945 */
1946
1947#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
1948
1949
1950#include <string>
1951
1952namespace Catch
1953{
1954 class Section
1955 {
1956 public:
1957 ///////////////////////////////////////////////////////////////////////
1958 Section
1959 (
1960 const std::string& name,
1961 const std::string& description,
1962 const std::string& filename,
1963 std::size_t line
1964 )
1965 : m_name( name ),
1966 m_sectionIncluded( Hub::getResultCapture().sectionStarted( name, description, filename, line, m_successes, m_failures ) )
1967 {
1968 }
1969
1970 ///////////////////////////////////////////////////////////////////////
1971 ~Section
1972 ()
1973 {
1974 if( m_sectionIncluded )
1975 Hub::getResultCapture().sectionEnded( m_name, m_successes, m_failures );
1976 }
1977
1978 ///////////////////////////////////////////////////////////////////////
1979 // This indicates whether the section should be executed or not
1980 operator bool
1981 ()
1982 {
1983 return m_sectionIncluded;
1984 }
1985
1986 private:
1987
1988 std::string m_name;
1989 std::size_t m_successes;
1990 std::size_t m_failures;
1991 bool m_sectionIncluded;
1992 };
1993
1994} // end namespace Catch
1995
1996#define INTERNAL_CATCH_SECTION( name, desc ) \
1997 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, __FILE__, __LINE__ ) )
1998
1999// #included from: internal/catch_generators.hpp
2000
2001/*
2002 * catch_generators.hpp
2003 * Catch
2004 *
2005 * Created by Phil on 27/01/2011.
2006 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
2007 *
2008 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2009 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2010 *
2011 */
2012
2013#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2014
2015
2016#include <iterator>
2017#include <vector>
2018#include <string>
2019#include <stdlib.h>
2020
2021namespace Catch
2022{
2023
2024template<typename T>
2025struct IGenerator
2026{
2027 virtual ~IGenerator
2028 ()
2029 {}
2030
2031 virtual T getValue
2032 ( std::size_t index
2033 ) const = 0;
2034
2035 virtual std::size_t size
2036 () const = 0;
2037};
2038
2039template<typename T>
2040class BetweenGenerator : public IGenerator<T>
2041{
2042public:
2043 ///////////////////////////////////////////////////////////////////////////
2044 BetweenGenerator
2045 (
2046 T from,
2047 T to
2048 )
2049 : m_from( from ),
2050 m_to( to )
2051 {
2052 }
2053
2054 ///////////////////////////////////////////////////////////////////////////
2055 virtual T getValue
2056 (
2057 std::size_t index
2058 )
2059 const
2060 {
2061 return m_from+static_cast<T>( index );
2062 }
2063
2064 ///////////////////////////////////////////////////////////////////////////
2065 virtual std::size_t size
2066 ()
2067 const
2068 {
2069 return 1+m_to-m_from;
2070 }
2071
2072private:
2073
2074 T m_from;
2075 T m_to;
2076};
2077
2078template<typename T>
2079class ValuesGenerator : public IGenerator<T>
2080{
2081public:
2082 ///////////////////////////////////////////////////////////////////////////
2083 ValuesGenerator
2084 ()
2085 {
2086 }
2087
2088 ///////////////////////////////////////////////////////////////////////////
2089 void add
2090 (
2091 T value
2092 )
2093 {
2094 m_values.push_back( value );
2095 }
2096
2097 ///////////////////////////////////////////////////////////////////////////
2098 virtual T getValue
2099 (
2100 std::size_t index
2101 )
2102 const
2103 {
2104 return m_values[index];
2105 }
2106
2107 ///////////////////////////////////////////////////////////////////////////
2108 virtual std::size_t size
2109 ()
2110 const
2111 {
2112 return m_values.size();
2113 }
2114
2115private:
2116
2117 std::vector<T> m_values;
2118};
2119
2120template<typename T>
2121class CompositeGenerator
2122{
2123public:
2124 ///////////////////////////////////////////////////////////////////////////
2125 CompositeGenerator()
2126 : m_totalSize( 0 )
2127 {
2128 }
2129
2130 ///////////////////////////////////////////////////////////////////////////
2131 // *** Move semantics, similar to auto_ptr ***
2132 CompositeGenerator( CompositeGenerator& other )
2133 : m_fileInfo( other.m_fileInfo ),
2134 m_totalSize( 0 )
2135 {
2136 move( other );
2137 }
2138
2139 ///////////////////////////////////////////////////////////////////////////
2140 CompositeGenerator& setFileInfo
2141 (
2142 const char* fileInfo
2143 )
2144 {
2145 m_fileInfo = fileInfo;
2146 return *this;
2147 }
2148
2149 ///////////////////////////////////////////////////////////////////////////
2150 ~CompositeGenerator
2151 ()
2152 {
2153 deleteAll( m_composed );
2154 }
2155
2156 ///////////////////////////////////////////////////////////////////////////
2157 operator T
2158 ()
2159 const
2160 {
2161 size_t overallIndex = Hub::getGeneratorIndex( m_fileInfo, m_totalSize );
2162
2163 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2164 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2165 for( size_t index = 0; it != itEnd; ++it )
2166 {
2167 const IGenerator<T>* generator = *it;
2168 if( overallIndex >= index && overallIndex < index + generator->size() )
2169 {
2170 return generator->getValue( overallIndex-index );
2171 }
2172 index += generator->size();
2173 }
2174 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
2175 return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
2176 }
2177
2178 ///////////////////////////////////////////////////////////////////////////
2179 void add
2180 (
2181 const IGenerator<T>* generator
2182 )
2183 {
2184 m_totalSize += generator->size();
2185 m_composed.push_back( generator );
2186 }
2187
2188 ///////////////////////////////////////////////////////////////////////////
2189 CompositeGenerator& then
2190 (
2191 CompositeGenerator& other
2192 )
2193 {
2194 move( other );
2195 return *this;
2196 }
2197
2198 ///////////////////////////////////////////////////////////////////////////
2199 CompositeGenerator& then
2200 (
2201 T value
2202 )
2203 {
2204 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2205 valuesGen->add( value );
2206 add( valuesGen );
2207 return *this;
2208 }
2209
2210private:
2211
2212 ///////////////////////////////////////////////////////////////////////////
2213 void move
2214 (
2215 CompositeGenerator& other
2216 )
2217 {
2218 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
2219 m_totalSize += other.m_totalSize;
2220 other.m_composed.clear();
2221 }
2222
2223 std::vector<const IGenerator<T>*> m_composed;
2224 std::string m_fileInfo;
2225 size_t m_totalSize;
2226};
2227
2228namespace Generators
2229{
2230 ///////////////////////////////////////////////////////////////////////////
2231 template<typename T>
2232 CompositeGenerator<T> between
2233 (
2234 T from,
2235 T to
2236 )
2237 {
2238 CompositeGenerator<T> generators;
2239 generators.add( new BetweenGenerator<T>( from, to ) );
2240 return generators;
2241 }
2242
2243 ///////////////////////////////////////////////////////////////////////////
2244 template<typename T>
2245 CompositeGenerator<T> values
2246 (
2247 T val1,
2248 T val2
2249 )
2250 {
2251 CompositeGenerator<T> generators;
2252 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2253 valuesGen->add( val1 );
2254 valuesGen->add( val2 );
2255 generators.add( valuesGen );
2256 return generators;
2257 }
2258
2259 ///////////////////////////////////////////////////////////////////////////
2260 template<typename T>
2261 CompositeGenerator<T> values
2262 (
2263 T val1,
2264 T val2,
2265 T val3
2266 )
2267 {
2268 CompositeGenerator<T> generators;
2269 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2270 valuesGen->add( val1 );
2271 valuesGen->add( val2 );
2272 valuesGen->add( val3 );
2273 generators.add( valuesGen );
2274 return generators;
2275 }
2276
2277 ///////////////////////////////////////////////////////////////////////////
2278 template<typename T>
2279 CompositeGenerator<T> values
2280 (
2281 T val1,
2282 T val2,
2283 T val3,
2284 T val4
2285 )
2286 {
2287 CompositeGenerator<T> generators;
2288 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2289 valuesGen->add( val1 );
2290 valuesGen->add( val2 );
2291 valuesGen->add( val3 );
2292 valuesGen->add( val4 );
2293 generators.add( valuesGen );
2294 return generators;
2295 }
2296
2297} // end namespace Generators
2298
2299using namespace Generators;
2300
2301} // end namespace Catch
2302
2303#define INTERNAL_CATCH_LINESTR2( line ) #line
2304#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2305
2306#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2307
2308// #included from: internal/catch_interfaces_exception.h
2309
2310/*
2311 * catch_exception_interfaces.h
2312 * Catch
2313 *
2314 * Created by Phil on 20/04/2011.
2315 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
2316 *
2317 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2318 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2319 *
2320 */
2321#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTIONS_H_INCLUDED
2322
2323#include <string>
2324
2325namespace Catch
2326{
2327 typedef std::string(*exceptionTranslateFunction)();
2328
2329 struct IExceptionTranslator
2330 {
2331 virtual ~IExceptionTranslator(){}
2332 virtual std::string translate() const = 0;
2333 };
2334
2335 struct IExceptionTranslatorRegistry
2336 {
2337 virtual ~IExceptionTranslatorRegistry
2338 ()
2339 {}
2340
2341 virtual void registerTranslator
2342 ( IExceptionTranslator* translator
2343 ) = 0;
2344 virtual std::string translateActiveException
2345 () const = 0;
2346
2347 };
2348
2349 class ExceptionTranslatorRegistrar
2350 {
2351 template<typename T>
2352 class ExceptionTranslator : public IExceptionTranslator
2353 {
2354 public:
2355
2356 ExceptionTranslator
2357 (
2358 std::string(*translateFunction)( T& )
2359 )
2360 : m_translateFunction( translateFunction )
2361 {}
2362
2363 virtual std::string translate
2364 ()
2365 const
2366 {
2367 try
2368 {
2369 throw;
2370 }
2371 catch( T& ex )
2372 {
2373 return m_translateFunction( ex );
2374 }
2375 }
2376
2377 protected:
2378 std::string(*m_translateFunction)( T& );
2379 };
2380
2381 public:
2382 template<typename T>
2383 ExceptionTranslatorRegistrar
2384 (
2385 std::string(*translateFunction)( T& )
2386 )
2387 {
2388 Catch::Hub::getExceptionTranslatorRegistry().registerTranslator
2389 ( new ExceptionTranslator<T>( translateFunction ) );
2390 }
2391 };
2392}
2393
2394///////////////////////////////////////////////////////////////////////////////
2395#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2396 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2397 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2398 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2399
2400// #included from: internal/catch_approx.hpp
2401
2402/*
2403 * catch_approx.hpp
2404 * Catch
2405 *
2406 * Created by Phil on 28/04/2011.
2407 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2408 *
2409 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2410 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2411 *
2412 */
2413#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2414
2415
2416#include <cmath>
2417#include <limits>
2418
2419namespace Catch
2420{
2421 namespace Detail
2422 {
2423 class Approx
2424 {
2425 public:
2426 ///////////////////////////////////////////////////////////////////////////
2427 explicit Approx
2428 (
Phil Nashf721a962011-06-07 14:13:57 +01002429 double value
Phil Nash89d1e6c2011-05-24 08:23:02 +01002430 )
Phil Nashf721a962011-06-07 14:13:57 +01002431 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
Phil Nash89d1e6c2011-05-24 08:23:02 +01002432 m_scale( 1.0 ),
Phil Nashf721a962011-06-07 14:13:57 +01002433 m_value( value )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002434 {
2435 }
2436
2437 ///////////////////////////////////////////////////////////////////////////
Phil Nashf721a962011-06-07 14:13:57 +01002438 Approx
2439 (
2440 const Approx& other
2441 )
2442 : m_epsilon( other.m_epsilon ),
2443 m_scale( other.m_scale ),
2444 m_value( other.m_value )
2445 {
2446 }
2447
2448 ///////////////////////////////////////////////////////////////////////////
2449 static Approx custom
2450 ()
2451 {
2452 return Approx( 0 );
2453 }
2454
2455 ///////////////////////////////////////////////////////////////////////////
2456 Approx operator()
2457 (
2458 double value
2459 )
2460 {
2461 Approx approx( value );
2462 approx.epsilon( m_epsilon );
2463 approx.scale( m_scale );
2464 return approx;
2465 }
2466
2467 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002468 friend bool operator ==
2469 (
Phil Nash6b6143c2011-05-31 07:51:04 +01002470 double lhs,
Phil Nash89d1e6c2011-05-24 08:23:02 +01002471 const Approx& rhs
2472 )
2473 {
2474 // Thanks to Richard Harris for his help refining this formula
Phil Nashf721a962011-06-07 14:13:57 +01002475 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01002476 }
2477
2478 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002479 friend bool operator ==
2480 (
2481 const Approx& lhs,
Phil Nash6b6143c2011-05-31 07:51:04 +01002482 double rhs
Phil Nash89d1e6c2011-05-24 08:23:02 +01002483 )
2484 {
2485 return operator==( rhs, lhs );
2486 }
2487
2488 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002489 friend bool operator !=
2490 (
Phil Nash6b6143c2011-05-31 07:51:04 +01002491 double lhs,
Phil Nash89d1e6c2011-05-24 08:23:02 +01002492 const Approx& rhs
2493 )
2494 {
2495 return !operator==( lhs, rhs );
2496 }
2497
2498 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002499 friend bool operator !=
2500 (
2501 const Approx& lhs,
Phil Nash6b6143c2011-05-31 07:51:04 +01002502 double rhs
Phil Nash89d1e6c2011-05-24 08:23:02 +01002503 )
2504 {
2505 return !operator==( rhs, lhs );
2506 }
2507
2508
2509 ///////////////////////////////////////////////////////////////////////////
2510 Approx& epsilon
2511 (
2512 double newEpsilon
2513 )
2514 {
2515 m_epsilon = newEpsilon;
2516 return *this;
2517 }
2518
2519 ///////////////////////////////////////////////////////////////////////////
2520 Approx& scale
2521 (
2522 double newScale
2523 )
2524 {
2525 m_scale = newScale;
2526 return *this;
2527 }
2528
2529 ///////////////////////////////////////////////////////////////////////////
2530 std::string toString() const
2531 {
2532 std::ostringstream oss;
Phil Nashf721a962011-06-07 14:13:57 +01002533 oss << "Approx( " << m_value << ")";
Phil Nash89d1e6c2011-05-24 08:23:02 +01002534 return oss.str();
2535 }
2536
2537 private:
2538 double m_epsilon;
2539 double m_scale;
Phil Nashf721a962011-06-07 14:13:57 +01002540 double m_value;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002541 };
2542 }
2543
2544 ///////////////////////////////////////////////////////////////////////////////
2545 template<>
2546 inline std::string toString<Detail::Approx>
2547 (
2548 const Detail::Approx& value
2549 )
2550 {
2551 return value.toString();
2552 }
2553
2554} // end namespace Catch
2555
Phil Nash83224e62011-08-12 18:53:28 +01002556// #included from: internal/catch_test_case_info.hpp
Phil Nash89d1e6c2011-05-24 08:23:02 +01002557
2558/*
2559 * catch_test_case_info.hpp
2560 * Catch
2561 *
2562 * Created by Phil on 29/10/2010.
2563 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2564 *
2565 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2566 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2567 *
2568 */
2569
2570#define TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED
2571
2572#include <map>
2573#include <string>
2574
2575namespace Catch
2576{
2577 class TestCaseInfo
2578 {
2579 public:
2580 ///////////////////////////////////////////////////////////////////////
2581 TestCaseInfo
2582 (
2583 ITestCase* testCase,
2584 const char* name,
2585 const char* description,
2586 const char* filename,
2587 std::size_t line
2588 )
2589 : m_test( testCase ),
2590 m_name( name ),
2591 m_description( description ),
2592 m_filename( filename ),
2593 m_line( line )
2594 {
2595 }
2596
2597 ///////////////////////////////////////////////////////////////////////
2598 TestCaseInfo
2599 ()
2600 : m_test( NULL )
2601 {
2602 }
2603
2604 ///////////////////////////////////////////////////////////////////////
2605 TestCaseInfo
2606 (
2607 const TestCaseInfo& other
2608 )
2609 : m_test( other.m_test->clone() ),
2610 m_name( other.m_name ),
2611 m_description( other.m_description ),
2612 m_filename( other.m_filename ),
2613 m_line( other.m_line )
2614 {
2615 }
2616
2617 ///////////////////////////////////////////////////////////////////////
2618 TestCaseInfo
2619 (
2620 const TestCaseInfo& other,
2621 const std::string& name
2622 )
2623 : m_test( other.m_test->clone() ),
2624 m_name( name ),
2625 m_description( other.m_description ),
2626 m_filename( other.m_filename ),
2627 m_line( other.m_line )
2628 {
2629 }
2630
2631 ///////////////////////////////////////////////////////////////////////
2632 TestCaseInfo& operator =
2633 (
2634 const TestCaseInfo& other
2635 )
2636 {
2637 TestCaseInfo temp( other );
2638 swap( temp );
2639 return *this;
2640 }
2641
2642 ///////////////////////////////////////////////////////////////////////
2643 ~TestCaseInfo
2644 ()
2645 {
2646 delete m_test;
2647 }
2648
2649 ///////////////////////////////////////////////////////////////////////
2650 void invoke
2651 ()
2652 const
2653 {
2654 m_test->invoke();
2655 }
2656
2657 ///////////////////////////////////////////////////////////////////////
2658 const std::string& getName
2659 ()
2660 const
2661 {
2662 return m_name;
2663 }
2664
2665 ///////////////////////////////////////////////////////////////////////
2666 const std::string& getDescription
2667 ()
2668 const
2669 {
2670 return m_description;
2671 }
2672
2673 ///////////////////////////////////////////////////////////////////////
2674 const std::string& getFilename
2675 ()
2676 const
2677 {
2678 return m_filename;
2679 }
2680
2681 ///////////////////////////////////////////////////////////////////////
2682 std::size_t getLine
2683 ()
2684 const
2685 {
2686 return m_line;
2687 }
2688
2689 ///////////////////////////////////////////////////////////////////////
2690 bool isHidden
2691 ()
2692 const
2693 {
2694 return m_name.size() >= 2 && m_name[0] == '.' && m_name[1] == '/';
2695 }
2696
2697 ///////////////////////////////////////////////////////////////////////
2698 void swap
2699 (
2700 TestCaseInfo& other
2701 )
2702 {
2703 std::swap( m_test, other.m_test );
2704 m_name.swap( other.m_name );
2705 m_description.swap( other.m_description );
2706 }
2707
2708 ///////////////////////////////////////////////////////////////////////
2709 bool operator ==
2710 (
2711 const TestCaseInfo& other
2712 )
2713 const
2714 {
2715 return *m_test == *other.m_test && m_name == other.m_name && m_description == other.m_description;
2716 }
2717
2718 ///////////////////////////////////////////////////////////////////////
2719 bool operator <
2720 (
2721 const TestCaseInfo& other
2722 )
2723 const
2724 {
2725 if( m_name < other.m_name )
2726 return true;
2727 if( m_name > other.m_name )
2728 return false;
2729
2730 return *m_test < *other.m_test;
2731 }
2732
2733 private:
2734 ITestCase* m_test;
2735 std::string m_name;
2736 std::string m_description;
2737 std::string m_filename;
2738 std::size_t m_line;
2739
2740 };
2741
2742 ///////////////////////////////////////////////////////////////////////////
2743 ///////////////////////////////////////////////////////////////////////////
2744
2745 class TestSpec
2746 {
2747 public:
2748 ///////////////////////////////////////////////////////////////////////
2749 TestSpec
2750 (
2751 const std::string& rawSpec
2752 )
2753 : m_rawSpec( rawSpec ),
2754 m_isWildcarded( false )
2755 {
2756 if( m_rawSpec[m_rawSpec.size()-1] == '*' )
2757 {
2758 m_rawSpec = m_rawSpec.substr( 0, m_rawSpec.size()-1 );
2759 m_isWildcarded = true;
2760 }
2761 }
2762
2763 ///////////////////////////////////////////////////////////////////////
2764 bool matches
2765 (
2766 const std::string& testName
2767 )
2768 const
2769 {
2770 if( !m_isWildcarded )
2771 return m_rawSpec == testName;
2772 else
2773 return testName.size() >= m_rawSpec.size() && testName.substr( 0, m_rawSpec.size() ) == m_rawSpec;
2774 }
2775
2776 private:
2777 std::string m_rawSpec;
2778 bool m_isWildcarded;
2779 };
2780}
2781
2782
Phil Nash81528252011-08-15 09:06:31 +01002783#ifdef __OBJC__
2784// #included from: internal/catch_objc.hpp
2785
2786/*
2787 * catch_objc.hpp
2788 * Catch
2789 *
2790 * Created by Phil on 14/11/2010.
2791 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2792 *
2793 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2794 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2795 *
2796 */
2797
2798#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2799
2800#import <objc/runtime.h>
2801#include <string>
2802
2803// NB. Any general catch headers included here must be included
2804// in catch.hpp first to make sure they are included by the single
2805// header for non obj-usage
2806
Phil Nash83224e62011-08-12 18:53:28 +01002807///////////////////////////////////////////////////////////////////////////////
2808// This protocol is really only here for (self) documenting purposes, since
2809// all its methods are optional.
2810@protocol OcFixture
2811
2812@optional
2813
2814-(void) setUp;
2815-(void) tearDown;
2816
2817@end
2818
2819namespace Catch
2820{
2821 class OcMethod : public ITestCase
2822 {
2823 public:
2824 ///////////////////////////////////////////////////////////////////////
2825 OcMethod
2826 (
2827 Class cls,
2828 SEL sel
2829 )
2830 : m_cls( cls ),
2831 m_sel( sel )
2832 {
2833 }
2834
2835 ///////////////////////////////////////////////////////////////////////
2836 virtual void invoke
2837 ()
2838 const
2839 {
2840 id obj = class_createInstance( m_cls, 0 );
2841 obj = [obj init];
2842
2843 if( [obj respondsToSelector: @selector(setUp) ] )
2844 [obj performSelector: @selector(setUp)];
2845
2846 if( [obj respondsToSelector: m_sel] )
2847 [obj performSelector: m_sel];
2848
2849 if( [obj respondsToSelector: @selector(tearDown) ] )
2850 [obj performSelector: @selector(tearDown)];
2851
2852 [obj release];
2853 }
2854
2855 ///////////////////////////////////////////////////////////////////////
2856 virtual ITestCase* clone
2857 ()
2858 const
2859 {
2860 return new OcMethod( m_cls, m_sel );
2861 }
2862
2863 ///////////////////////////////////////////////////////////////////////
2864 virtual bool operator ==
2865 (
2866 const ITestCase& other
2867 )
2868 const
2869 {
2870 const OcMethod* ocmOther = dynamic_cast<const OcMethod*> ( &other );
2871 return ocmOther && ocmOther->m_sel == m_sel;
2872 }
2873
2874 ///////////////////////////////////////////////////////////////////////
2875 virtual bool operator <
2876 (
2877 const ITestCase& other
2878 )
2879 const
2880 {
2881 const OcMethod* ocmOther = dynamic_cast<const OcMethod*> ( &other );
2882 return ocmOther && ocmOther->m_sel < m_sel;
2883 }
2884
2885 private:
2886 Class m_cls;
2887 SEL m_sel;
2888 };
2889
2890 namespace Detail
2891 {
2892
2893 ///////////////////////////////////////////////////////////////////////
2894 inline bool startsWith
2895 (
2896 const std::string& str,
2897 const std::string& sub
2898 )
2899 {
2900 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
2901 }
2902
2903 ///////////////////////////////////////////////////////////////////////
2904 inline const char* getAnnotation
2905 (
2906 Class cls,
2907 const std::string& annotationName,
2908 const std::string& testCaseName
2909 )
2910 {
2911 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2912 SEL sel = NSSelectorFromString( selStr );
2913 [selStr release];
2914 if( [cls respondsToSelector: sel] )
2915 return (const char*)[cls performSelector: sel];
2916 return "";
2917 }
2918 }
2919
2920 ///////////////////////////////////////////////////////////////////////////
2921 inline size_t registerTestMethods
2922 ()
2923 {
2924 size_t noTestMethods = 0;
2925 int noClasses = objc_getClassList( NULL, 0 );
2926
2927 std::vector<Class> classes( noClasses );
2928 objc_getClassList( &classes[0], noClasses );
2929
2930 for( int c = 0; c < noClasses; c++ )
2931 {
2932 Class cls = classes[c];
2933 {
2934 u_int count;
2935 Method* methods = class_copyMethodList( cls, &count );
2936 for( int m = 0; m < count ; m++ )
2937 {
2938 SEL selector = method_getName(methods[m]);
2939 std::string methodName = sel_getName(selector);
2940 if( Detail::startsWith( methodName, "Catch_TestCase_" ) )
2941 {
2942 std::string testCaseName = methodName.substr( 15 );
2943 const char* name = Detail::getAnnotation( cls, "Name", testCaseName );
2944 const char* desc = Detail::getAnnotation( cls, "Description", testCaseName );
2945
2946 Hub::getTestCaseRegistry().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name, desc, "", 0 ) );
2947 noTestMethods++;
2948
2949 }
2950 }
2951 free(methods);
2952 }
2953 }
2954 return noTestMethods;
2955 }
2956}
2957
2958///////////////////////////////////////////////////////////////////////////////
2959#define OC_TEST_CASE( name, desc )\
2960+(const char*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
2961{\
2962return name; \
2963}\
2964+(const char*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
2965{ \
2966return desc; \
2967} \
2968-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2969
2970#endif
2971
2972#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
2973// #included from: catch_runner.hpp
2974
2975/*
2976 * catch_runner.hpp
2977 * Catch
2978 *
2979 * Created by Phil on 31/10/2010.
2980 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2981 *
2982 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2983 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2984 *
2985 */
2986
2987#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
2988
2989// #included from: internal/catch_hub_impl.hpp
2990
2991/*
2992 * catch_hub_impl.hpp
2993 * Catch
2994 *
2995 * Created by Phil on 31/12/2010.
2996 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2997 *
2998 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2999 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3000 *
3001 */
3002// #included from: catch_reporter_registry.hpp
3003
3004/*
3005 * catch_reporter_registry.hpp
3006 * Catch
3007 *
3008 * Created by Phil on 29/10/2010.
3009 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
3010 *
3011 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3012 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3013 *
3014 */
3015#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
3016
3017
3018#include <map>
3019
3020namespace Catch
3021{
3022 class ReporterRegistry : public IReporterRegistry
3023 {
3024 public:
3025
3026 ///////////////////////////////////////////////////////////////////////
3027 ~ReporterRegistry
3028 ()
3029 {
3030 deleteAllValues( m_factories );
3031 }
3032
3033 ///////////////////////////////////////////////////////////////////////
3034 virtual IReporter* create
3035 (
3036 const std::string& name,
3037 const IReporterConfig& config
3038 )
3039 const
3040 {
3041 FactoryMap::const_iterator it = m_factories.find( name );
3042 if( it == m_factories.end() )
3043 return NULL;
3044 return it->second->create( config );
3045 }
3046
3047 ///////////////////////////////////////////////////////////////////////
3048 void registerReporter
3049 (
3050 const std::string& name,
3051 IReporterFactory* factory
3052 )
3053 {
3054 m_factories.insert( std::make_pair( name, factory ) );
3055 }
3056
3057 ///////////////////////////////////////////////////////////////////////
3058 const FactoryMap& getFactories
3059 ()
3060 const
3061 {
3062 return m_factories;
3063 }
3064
3065 private:
3066 FactoryMap m_factories;
3067 };
3068}
3069
3070// #included from: catch_test_case_registry_impl.hpp
3071
3072/*
3073 * catch_test_case_registry_impl.hpp
3074 * Catch
3075 *
3076 * Created by Phil on 7/1/2011
3077 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
3078 *
3079 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3080 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3081 *
3082 */
3083
3084
Phil Nash89d1e6c2011-05-24 08:23:02 +01003085#include <vector>
3086#include <set>
3087#include <sstream>
3088
3089#include <iostream> // !TBD DBG
3090namespace Catch
3091{
3092 class TestRegistry : public ITestCaseRegistry
3093 {
3094 public:
3095 ///////////////////////////////////////////////////////////////////////////
3096 TestRegistry
3097 ()
3098 : m_unnamedCount( 0 )
3099 {
3100 }
3101
3102 ///////////////////////////////////////////////////////////////////////////
3103 virtual void registerTest
3104 (
3105 const TestCaseInfo& testInfo
3106 )
3107 {
3108 if( testInfo.getName() == "" )
3109 {
3110 std::ostringstream oss;
3111 oss << testInfo.getName() << "unnamed/" << ++m_unnamedCount;
3112 return registerTest( TestCaseInfo( testInfo, oss.str() ) );
3113 }
3114 if( m_functions.find( testInfo ) == m_functions.end() )
3115 {
3116 m_functions.insert( testInfo );
3117 m_functionsInOrder.push_back( testInfo );
3118 }
3119 }
3120
3121 ///////////////////////////////////////////////////////////////////////////
3122 virtual const std::vector<TestCaseInfo>& getAllTests
3123 ()
3124 const
3125 {
3126 return m_functionsInOrder;
3127 }
3128
3129 ///////////////////////////////////////////////////////////////////////////
3130 virtual std::vector<TestCaseInfo> getMatchingTestCases
3131 (
3132 const std::string& rawTestSpec
3133 )
3134 {
3135 TestSpec testSpec( rawTestSpec );
3136
3137 std::vector<TestCaseInfo> testList;
3138 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
3139 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
3140 for(; it != itEnd; ++it )
3141 {
3142 if( testSpec.matches( it->getName() ) )
3143 {
3144 testList.push_back( *it );
3145 std::cout << it->getName() << std::endl;
3146 }
3147 }
3148 return testList;
3149 }
3150
3151 private:
3152
3153 std::set<TestCaseInfo> m_functions;
3154 std::vector<TestCaseInfo> m_functionsInOrder;
3155 size_t m_unnamedCount;
3156 };
3157
3158 ///////////////////////////////////////////////////////////////////////////
3159 ///////////////////////////////////////////////////////////////////////////
3160
3161
3162 struct FreeFunctionTestCase : ITestCase
3163 {
3164 ///////////////////////////////////////////////////////////////////////////
3165 FreeFunctionTestCase
3166 (
3167 TestFunction fun
3168 )
3169 : m_fun( fun )
3170 {}
3171
3172 ///////////////////////////////////////////////////////////////////////////
3173 virtual void invoke
3174 ()
3175 const
3176 {
3177 m_fun();
3178 }
3179
3180 ///////////////////////////////////////////////////////////////////////////
3181 virtual ITestCase* clone
3182 ()
3183 const
3184 {
3185 return new FreeFunctionTestCase( m_fun );
3186 }
3187
3188 ///////////////////////////////////////////////////////////////////////////
3189 virtual bool operator ==
3190 (
3191 const ITestCase& other
3192 )
3193 const
3194 {
3195 const FreeFunctionTestCase* ffOther = dynamic_cast<const FreeFunctionTestCase*> ( &other );
3196 return ffOther && m_fun == ffOther->m_fun;
3197 }
3198
3199 ///////////////////////////////////////////////////////////////////////////
3200 virtual bool operator <
3201 (
3202 const ITestCase& other
3203 )
3204 const
3205 {
3206 const FreeFunctionTestCase* ffOther = dynamic_cast<const FreeFunctionTestCase*> ( &other );
3207 return ffOther && m_fun < ffOther->m_fun;
3208 }
3209
3210 private:
3211 TestFunction m_fun;
3212 };
3213
3214 ///////////////////////////////////////////////////////////////////////////
3215 ///////////////////////////////////////////////////////////////////////////
3216
3217 ///////////////////////////////////////////////////////////////////////////
3218 AutoReg::AutoReg
3219 (
3220 TestFunction function,
3221 const char* name,
3222 const char* description,
3223 const char* filename,
3224 std::size_t line
3225 )
3226 {
3227 registerTestCase( new FreeFunctionTestCase( function ), name, description, filename, line );
3228 }
3229
3230 ///////////////////////////////////////////////////////////////////////////
3231 AutoReg::~AutoReg
3232 ()
3233 {
3234 }
3235
3236 ///////////////////////////////////////////////////////////////////////////
3237 void AutoReg::registerTestCase
3238 (
3239 ITestCase* testCase,
3240 const char* name,
3241 const char* description,
3242 const char* filename,
3243 std::size_t line
3244 )
3245 {
3246 Hub::getTestCaseRegistry().registerTest( TestCaseInfo( testCase, name, description, filename, line ) );
3247 }
3248
3249} // end namespace Catch
3250
3251// #included from: catch_exception_translator_registry.hpp
3252
3253/*
3254 * catch_exception_translator_registry.hpp
3255 * Catch
3256 *
3257 * Created by Phil on 20/04/2011.
3258 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
3259 *
3260 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3261 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3262 *
3263 */
3264#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_HPP_INCLUDED
3265
3266
3267namespace Catch
3268{
3269 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry
3270 {
3271 ///////////////////////////////////////////////////////////////////////
3272 virtual void registerTranslator
3273 (
3274 IExceptionTranslator* translator
3275 )
3276 {
3277 m_translators.push_back( translator );
3278 }
3279
3280 ///////////////////////////////////////////////////////////////////////
3281 virtual std::string translateActiveException
3282 ()
3283 const
3284 {
3285 return tryTranslators( m_translators.begin() );
3286 }
3287
3288 ///////////////////////////////////////////////////////////////////////
3289 std::string tryTranslators
3290 (
3291 std::vector<IExceptionTranslator*>::const_iterator it
3292 )
3293 const
3294 {
3295 if( it == m_translators.end() )
3296 return "Unknown exception";
3297
3298 try
3299 {
3300 return (*it)->translate();
3301 }
3302 catch(...)
3303 {
3304 return tryTranslators( it+1 );
3305 }
3306 }
3307
3308 private:
3309 std::vector<IExceptionTranslator*> m_translators;
3310 };
3311}
3312
3313// #included from: catch_runner_impl.hpp
3314
3315/*
3316 * catch_runner.hpp
3317 * Catch
3318 *
3319 * Created by Phil on 22/10/2010.
3320 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
3321 *
3322 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3323 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3324 *
3325 */
3326#define TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED
3327
3328// #included from: catch_interfaces_runner.h
3329
3330/*
3331 * catch_interfaces_runner.h
3332 * Catch
3333 *
3334 * Created by Phil on 07/01/2011.
3335 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
3336 *
3337 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3338 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3339 *
3340 */
3341#define TWOBLUECUBES_INTERNAL_CATCH_INTERFACES_RUNNER_H_INCLUDED
3342
3343#include <string>
3344
3345namespace Catch
3346{
3347 class TestCaseInfo;
3348
3349 struct IRunner
3350 {
3351 virtual ~IRunner
3352 ()
3353 {}
3354
3355 virtual void runAll
3356 ( bool runHiddenTests = false
3357 ) = 0;
3358
3359 virtual std::size_t runMatching
3360 ( const std::string& rawTestSpec
3361 ) = 0;
3362
3363 virtual std::size_t getSuccessCount
3364 () const = 0;
3365
3366 virtual std:: size_t getFailureCount
3367 () const = 0;
3368
3369 };
3370}
3371
3372// #included from: catch_config.hpp
3373
3374/*
3375 * catch_config.hpp
3376 * Catch
3377 *
3378 * Created by Phil on 08/11/2010.
3379 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
3380 *
3381 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3382 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3383 *
3384 */
3385
3386#define TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
3387
3388
3389#include <memory>
3390#include <vector>
3391#include <string>
3392#include <iostream>
3393
3394namespace Catch
3395{
3396
3397 class Config : public IReporterConfig
3398 {
3399 private:
3400 Config( const Config& other );
3401 Config& operator = ( const Config& other );
3402 public:
3403
3404 struct Include { enum What
3405 {
3406 FailedOnly,
3407 SuccessfulResults
3408 }; };
3409
3410 struct List{ enum What
3411 {
3412 None = 0,
3413
3414 Reports = 1,
3415 Tests = 2,
3416 All = 3,
3417
3418 WhatMask = 0xf,
3419
3420 AsText = 0x10,
3421 AsXml = 0x11,
3422
3423 AsMask = 0xf0
3424 }; };
3425
3426
3427 ///////////////////////////////////////////////////////////////////////////
3428 Config()
3429 : m_reporter( NULL ),
3430 m_listSpec( List::None ),
3431 m_shouldDebugBreak( false ),
3432 m_showHelp( false ),
Phil Nash48112c22011-05-31 18:47:30 +01003433 m_streambuf( NULL ),
3434 m_os( std::cout.rdbuf() ),
Phil Nash89d1e6c2011-05-24 08:23:02 +01003435 m_includeWhat( Include::FailedOnly )
3436 {}
3437
3438 ///////////////////////////////////////////////////////////////////////////
3439 ~Config()
3440 {
Phil Nash48112c22011-05-31 18:47:30 +01003441 m_os.rdbuf( std::cout.rdbuf() );
3442 delete m_streambuf;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003443 }
3444
3445 ///////////////////////////////////////////////////////////////////////////
3446 void setReporter( const std::string& reporterName )
3447 {
3448 if( m_reporter.get() )
3449 return setError( "Only one reporter may be specified" );
3450 setReporter( Hub::getReporterRegistry().create( reporterName, *this ) );
3451 }
3452
3453 ///////////////////////////////////////////////////////////////////////////
3454 void addTestSpec( const std::string& testSpec )
3455 {
3456 m_testSpecs.push_back( testSpec );
3457 }
3458
3459 ///////////////////////////////////////////////////////////////////////////
3460 bool testsSpecified() const
3461 {
3462 return !m_testSpecs.empty();
3463 }
3464
3465 ///////////////////////////////////////////////////////////////////////////
3466 const std::vector<std::string>& getTestSpecs() const
3467 {
3468 return m_testSpecs;
3469 }
3470
3471 ///////////////////////////////////////////////////////////////////////////
3472 List::What getListSpec( void ) const
3473 {
3474 return m_listSpec;
3475 }
3476
3477 ///////////////////////////////////////////////////////////////////////////
3478 void setListSpec( List::What listSpec )
3479 {
3480 m_listSpec = listSpec;
3481 }
3482
3483 ///////////////////////////////////////////////////////////////////////////
3484 void setFilename( const std::string& filename )
3485 {
3486 m_filename = filename;
3487 }
3488
3489 ///////////////////////////////////////////////////////////////////////////
3490 const std::string& getFilename() const
3491 {
3492 return m_filename;
3493 }
3494
3495 ///////////////////////////////////////////////////////////////////////////
3496 const std::string& getMessage() const
3497 {
3498 return m_message;
3499 }
3500
3501 ///////////////////////////////////////////////////////////////////////////
3502 void setError( const std::string& errorMessage )
3503 {
3504 m_message = errorMessage + "\n\n" + "Usage: ...";
3505 }
3506
3507 ///////////////////////////////////////////////////////////////////////////
3508 void setReporter( IReporter* reporter )
3509 {
3510 m_reporter = std::auto_ptr<IReporter>( reporter );
3511 }
3512
3513 ///////////////////////////////////////////////////////////////////////////
3514 IReporter* getReporter() const
3515 {
3516 if( !m_reporter.get() )
3517 const_cast<Config*>( this )->setReporter( Hub::getReporterRegistry().create( "basic", *this ) );
3518 return m_reporter.get();
3519 }
3520
3521 ///////////////////////////////////////////////////////////////////////////
3522 List::What listWhat() const
3523 {
3524 return static_cast<List::What>( m_listSpec & List::WhatMask );
3525 }
3526
3527 ///////////////////////////////////////////////////////////////////////////
3528 List::What listAs() const
3529 {
3530 return static_cast<List::What>( m_listSpec & List::AsMask );
3531 }
3532
3533 ///////////////////////////////////////////////////////////////////////////
3534 void setIncludeWhat( Include::What includeWhat )
3535 {
3536 m_includeWhat = includeWhat;
3537 }
3538
3539 ///////////////////////////////////////////////////////////////////////////
3540 void setShouldDebugBreak( bool shouldDebugBreakFlag )
3541 {
3542 m_shouldDebugBreak = shouldDebugBreakFlag;
3543 }
3544
3545 ///////////////////////////////////////////////////////////////////////////
3546 void setName( const std::string& name )
3547 {
3548 m_name = name;
3549 }
3550
3551 ///////////////////////////////////////////////////////////////////////////
3552 std::string getName() const
3553 {
3554 return m_name;
3555 }
3556
3557 ///////////////////////////////////////////////////////////////////////////
3558 bool shouldDebugBreak() const
3559 {
3560 return m_shouldDebugBreak;
3561 }
3562
3563 ///////////////////////////////////////////////////////////////////////////
3564 void setShowHelp( bool showHelpFlag )
3565 {
3566 m_showHelp = showHelpFlag;
3567 }
3568
3569 ///////////////////////////////////////////////////////////////////////////
3570 bool showHelp() const
3571 {
3572 return m_showHelp;
3573 }
3574
3575 ///////////////////////////////////////////////////////////////////////////
3576 virtual std::ostream& stream() const
3577 {
3578 return m_os;
3579 }
3580
3581 ///////////////////////////////////////////////////////////////////////////
3582 void setStreamBuf( std::streambuf* buf )
3583 {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003584 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
3585 }
3586
3587 ///////////////////////////////////////////////////////////////////////////
3588 void useStream( const std::string& streamName )
3589 {
Phil Nash48112c22011-05-31 18:47:30 +01003590 std::streambuf* newBuf = Hub::createStreamBuf( streamName );
3591 setStreamBuf( newBuf );
3592 delete m_streambuf;
3593 m_streambuf = newBuf;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003594 }
3595
3596 ///////////////////////////////////////////////////////////////////////////
3597 virtual bool includeSuccessfulResults() const
3598 {
3599 return m_includeWhat == Include::SuccessfulResults;
3600 }
3601
3602 private:
3603 std::auto_ptr<IReporter> m_reporter;
3604 std::string m_filename;
3605 std::string m_message;
3606 List::What m_listSpec;
3607 std::vector<std::string> m_testSpecs;
3608 bool m_shouldDebugBreak;
3609 bool m_showHelp;
3610 std::streambuf* m_streambuf;
3611 mutable std::ostream m_os;
3612 Include::What m_includeWhat;
3613 std::string m_name;
3614
3615 };
3616
3617} // end namespace Catch
3618
3619
3620#include <set>
3621#include <string>
3622
3623namespace Catch
3624{
3625
3626 class StreamRedirect
3627 {
3628 public:
3629 ///////////////////////////////////////////////////////////////////////
3630 StreamRedirect
3631 (
3632 std::ostream& stream,
3633 std::string& targetString
3634 )
3635 : m_stream( stream ),
3636 m_prevBuf( stream.rdbuf() ),
3637 m_targetString( targetString )
3638 {
3639 stream.rdbuf( m_oss.rdbuf() );
3640 }
3641
3642 ///////////////////////////////////////////////////////////////////////
3643 ~StreamRedirect
3644 ()
3645 {
3646 m_targetString = m_oss.str();
3647 m_stream.rdbuf( m_prevBuf );
3648 }
3649
3650 private:
3651 std::ostream& m_stream;
3652 std::streambuf* m_prevBuf;
3653 std::ostringstream m_oss;
3654 std::string& m_targetString;
3655 };
3656
3657
3658 ///////////////////////////////////////////////////////////////////////////
3659 ///////////////////////////////////////////////////////////////////////////
3660 class SectionInfo
3661 {
3662 public:
3663 enum Status
3664 {
3665 Root,
3666 Unknown,
3667 NonLeaf,
Phil Nash89d1e6c2011-05-24 08:23:02 +01003668 TestedLeaf
3669 };
3670
3671 ///////////////////////////////////////////////////////////////////////
3672 SectionInfo
3673 (
3674 SectionInfo* parent
3675 )
3676 : m_status( Unknown ),
3677 m_parent( parent )
3678 {
3679 }
3680
3681 ///////////////////////////////////////////////////////////////////////
3682 SectionInfo
3683 ()
3684 : m_status( Root ),
3685 m_parent( NULL )
3686 {
3687 }
3688
3689 ///////////////////////////////////////////////////////////////////////
3690 ~SectionInfo
3691 ()
3692 {
3693 deleteAllValues( m_subSections );
3694 }
3695
3696 ///////////////////////////////////////////////////////////////////////
3697 bool shouldRun
3698 ()
3699 const
3700 {
3701 return m_status != TestedLeaf;
3702 }
3703
3704 ///////////////////////////////////////////////////////////////////////
3705 bool ran
3706 ()
3707 {
3708 if( m_status != NonLeaf )
3709 {
3710 m_status = TestedLeaf;
3711 return true;
3712 }
3713 return false;
3714 }
3715
3716 ///////////////////////////////////////////////////////////////////////
Phil Nash3c20a752011-06-23 08:23:33 +01003717 SectionInfo* findSubSection
Phil Nash89d1e6c2011-05-24 08:23:02 +01003718 (
3719 const std::string& name
3720 )
3721 {
3722 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.find( name );
Phil Nash3c20a752011-06-23 08:23:33 +01003723 return it != m_subSections.end()
3724 ? it->second
3725 : NULL;
3726 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003727
Phil Nash3c20a752011-06-23 08:23:33 +01003728 ///////////////////////////////////////////////////////////////////////
3729 SectionInfo* addSubSection
3730 (
3731 const std::string& name
3732 )
3733 {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003734 SectionInfo* subSection = new SectionInfo( this );
3735 m_subSections.insert( std::make_pair( name, subSection ) );
3736 m_status = NonLeaf;
3737 return subSection;
3738 }
3739
3740 ///////////////////////////////////////////////////////////////////////
3741 SectionInfo* getParent
3742 ()
3743 {
3744 return m_parent;
3745 }
3746
3747 ///////////////////////////////////////////////////////////////////////
3748 bool hasUntestedSections
3749 ()
3750 const
3751 {
Phil Nash3c20a752011-06-23 08:23:33 +01003752 if( m_status == Unknown )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003753 return true;
3754
3755 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.begin();
3756 std::map<std::string, SectionInfo*>::const_iterator itEnd = m_subSections.end();
3757 for(; it != itEnd; ++it )
3758 {
3759 if( it->second->hasUntestedSections() )
3760 return true;
3761 }
3762 return false;
3763 }
3764
3765 private:
3766 Status m_status;
3767 std::map<std::string, SectionInfo*> m_subSections;
3768 SectionInfo* m_parent;
3769 };
3770
3771 ///////////////////////////////////////////////////////////////////////////
3772 ///////////////////////////////////////////////////////////////////////////
3773
3774 class RunningTest
3775 {
3776 enum RunStatus
3777 {
3778 NothingRun,
3779 EncounteredASection,
3780 RanAtLeastOneSection,
3781 RanToCompletionWithSections,
3782 RanToCompletionWithNoSections
3783 };
3784
3785 public:
3786 ///////////////////////////////////////////////////////////////////////
3787 explicit RunningTest
3788 (
3789 const TestCaseInfo* info = NULL
3790 )
3791 : m_info( info ),
3792 m_runStatus( RanAtLeastOneSection ),
Phil Nash3c20a752011-06-23 08:23:33 +01003793 m_currentSection( &m_rootSection ),
3794 m_changed( false )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003795 {
3796 }
3797
3798 ///////////////////////////////////////////////////////////////////////
3799 bool wasSectionSeen
3800 ()
3801 const
3802 {
3803 return m_runStatus == RanAtLeastOneSection ||
3804 m_runStatus == RanToCompletionWithSections;
3805 }
3806
3807 ///////////////////////////////////////////////////////////////////////
3808 void reset
3809 ()
3810 {
3811 m_runStatus = NothingRun;
Phil Nash3c20a752011-06-23 08:23:33 +01003812 m_changed = false;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003813 }
3814
3815 ///////////////////////////////////////////////////////////////////////
3816 void ranToCompletion
3817 ()
3818 {
3819 m_runStatus = m_runStatus == RanAtLeastOneSection ||
3820 m_runStatus == EncounteredASection
3821 ? RanToCompletionWithSections
3822 : RanToCompletionWithNoSections;
3823 }
3824
3825 ///////////////////////////////////////////////////////////////////////
3826 bool addSection
3827 (
3828 const std::string& name
3829 )
3830 {
3831 if( m_runStatus == NothingRun )
3832 m_runStatus = EncounteredASection;
3833
Phil Nash3c20a752011-06-23 08:23:33 +01003834 SectionInfo* thisSection = m_currentSection->findSubSection( name );
3835 if( !thisSection )
3836 {
3837 thisSection = m_currentSection->addSubSection( name );
3838 m_changed = true;
3839 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003840
3841 if( !wasSectionSeen() && thisSection->shouldRun() )
3842 {
3843 m_currentSection = thisSection;
3844 return true;
3845 }
3846 return false;
3847 }
3848
3849 ///////////////////////////////////////////////////////////////////////
3850 void endSection
3851 (
3852 const std::string&
3853 )
3854 {
3855 if( m_currentSection->ran() )
Phil Nash3c20a752011-06-23 08:23:33 +01003856 {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003857 m_runStatus = RanAtLeastOneSection;
Phil Nash3c20a752011-06-23 08:23:33 +01003858 m_changed = true;
3859 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003860 m_currentSection = m_currentSection->getParent();
3861 }
3862
3863 ///////////////////////////////////////////////////////////////////////
3864 const TestCaseInfo& getTestCaseInfo
3865 ()
3866 const
3867 {
3868 return *m_info;
3869 }
3870
3871 ///////////////////////////////////////////////////////////////////////
3872 bool hasUntestedSections
3873 ()
3874 const
3875 {
Phil Nash3c20a752011-06-23 08:23:33 +01003876 return m_runStatus == RanAtLeastOneSection ||
3877 ( m_rootSection.hasUntestedSections() && m_changed );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003878 }
3879
3880 private:
3881 const TestCaseInfo* m_info;
3882 RunStatus m_runStatus;
3883 SectionInfo m_rootSection;
3884 SectionInfo* m_currentSection;
Phil Nash3c20a752011-06-23 08:23:33 +01003885 bool m_changed;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003886 };
3887
3888 ///////////////////////////////////////////////////////////////////////////
3889 ///////////////////////////////////////////////////////////////////////////
3890 class Runner : public IResultCapture, public IRunner
3891 {
3892 Runner( const Runner& );
3893 void operator =( const Runner& );
3894
3895 public:
3896
3897 ///////////////////////////////////////////////////////////////////////////
3898 explicit Runner
3899 (
3900 const Config& config
3901 )
3902 : m_runningTest( NULL ),
3903 m_config( config ),
3904 m_successes( 0 ),
3905 m_failures( 0 ),
3906 m_reporter( m_config.getReporter() ),
3907 m_prevRunner( &Hub::getRunner() ),
3908 m_prevResultCapture( &Hub::getResultCapture() )
3909 {
3910 Hub::setRunner( this );
3911 Hub::setResultCapture( this );
3912 m_reporter->StartTesting();
3913 }
3914
3915 ///////////////////////////////////////////////////////////////////////////
3916 ~Runner
3917 ()
3918 {
3919 m_reporter->EndTesting( m_successes, m_failures );
3920 Hub::setRunner( m_prevRunner );
3921 Hub::setResultCapture( m_prevResultCapture );
3922 }
3923
3924 ///////////////////////////////////////////////////////////////////////////
3925 virtual void runAll
3926 (
3927 bool runHiddenTests = false
3928 )
3929 {
3930 std::vector<TestCaseInfo> allTests = Hub::getTestCaseRegistry().getAllTests();
3931 for( std::size_t i=0; i < allTests.size(); ++i )
3932 {
3933 if( runHiddenTests || !allTests[i].isHidden() )
3934 runTest( allTests[i] );
3935 }
3936 }
3937
3938 ///////////////////////////////////////////////////////////////////////////
3939 virtual std::size_t runMatching
3940 (
3941 const std::string& rawTestSpec
3942 )
3943 {
3944 TestSpec testSpec( rawTestSpec );
3945
3946 std::vector<TestCaseInfo> allTests = Hub::getTestCaseRegistry().getAllTests();
3947 std::size_t testsRun = 0;
3948 for( std::size_t i=0; i < allTests.size(); ++i )
3949 {
3950 if( testSpec.matches( allTests[i].getName() ) )
3951 {
3952 runTest( allTests[i] );
3953 testsRun++;
3954 }
3955 }
3956 return testsRun;
3957 }
3958
3959 ///////////////////////////////////////////////////////////////////////////
3960 void runTest
3961 (
3962 const TestCaseInfo& testInfo
3963 )
3964 {
3965 std::size_t prevSuccessCount = m_successes;
3966 std::size_t prevFailureCount = m_failures;
3967
3968 std::string redirectedCout;
3969 std::string redirectedCerr;
3970
3971 m_reporter->StartTestCase( testInfo );
3972
3973 m_runningTest = new RunningTest( &testInfo );
3974
3975 do
3976 {
3977 do
3978 {
3979 m_currentResult.setFileAndLine( m_runningTest->getTestCaseInfo().getFilename(),
3980 m_runningTest->getTestCaseInfo().getLine() );
3981 runCurrentTest( redirectedCout, redirectedCerr );
3982 }
3983 while( m_runningTest->hasUntestedSections() );
3984 }
3985 while( Hub::advanceGeneratorsForCurrentTest() );
3986
3987 delete m_runningTest;
3988 m_runningTest = NULL;
3989
3990 m_reporter->EndTestCase( testInfo, m_successes - prevSuccessCount, m_failures - prevFailureCount, redirectedCout, redirectedCerr );
3991 }
3992
3993 ///////////////////////////////////////////////////////////////////////////
3994 virtual std::size_t getSuccessCount
3995 ()
3996 const
3997 {
3998 return m_successes;
3999 }
4000
4001 ///////////////////////////////////////////////////////////////////////////
4002 virtual std:: size_t getFailureCount
4003 ()
4004 const
4005 {
4006 return m_failures;
4007 }
4008
4009 private: // IResultCapture
4010
4011 ///////////////////////////////////////////////////////////////////////////
4012 virtual ResultAction::Value acceptResult
4013 (
4014 bool result
4015 )
4016 {
4017 return acceptResult( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
4018 }
4019
4020 ///////////////////////////////////////////////////////////////////////////
4021 virtual ResultAction::Value acceptResult
4022 (
4023 ResultWas::OfType result
4024 )
4025 {
4026 m_currentResult.setResultType( result );
4027 return actOnCurrentResult();
4028 }
4029
4030 ///////////////////////////////////////////////////////////////////////////
4031 virtual ResultAction::Value acceptExpression
4032 (
4033 const MutableResultInfo& resultInfo
4034 )
4035 {
4036 m_currentResult = resultInfo;
4037 return actOnCurrentResult();
4038 }
4039
4040 ///////////////////////////////////////////////////////////////////////////
4041 virtual void acceptMessage
4042 (
4043 const std::string& msg
4044 )
4045 {
4046 m_currentResult.setMessage( msg );
4047 }
4048
4049 ///////////////////////////////////////////////////////////////////////////
4050 virtual void testEnded
4051 (
4052 const ResultInfo& result
4053 )
4054 {
4055 if( result.getResultType() == ResultWas::Ok )
4056 {
4057 m_successes++;
4058 }
4059 else if( !result.ok() )
4060 {
4061 m_failures++;
4062
4063 std::vector<ResultInfo>::const_iterator it = m_info.begin();
4064 std::vector<ResultInfo>::const_iterator itEnd = m_info.end();
4065 for(; it != itEnd; ++it )
4066 m_reporter->Result( *it );
4067 m_info.clear();
4068 }
4069
4070 if( result.getResultType() == ResultWas::Info )
4071 m_info.push_back( result );
4072 else
4073 m_reporter->Result( result );
4074 }
4075
4076 ///////////////////////////////////////////////////////////////////////////
4077 virtual bool sectionStarted
4078 (
4079 const std::string& name,
4080 const std::string& description,
4081 const std::string& filename,
4082 std::size_t line,
4083 std::size_t& successes,
4084 std::size_t& failures
4085 )
4086 {
4087 std::ostringstream oss;
4088 oss << filename << ":" << line;
4089
4090 if( !m_runningTest->addSection( oss.str() ) )
4091 return false;
4092
4093 m_currentResult.setFileAndLine( filename, line );
4094 m_reporter->StartSection( name, description );
4095 successes = m_successes;
4096 failures = m_failures;
4097
4098 return true;
4099 }
4100
4101 ///////////////////////////////////////////////////////////////////////////
4102 virtual void sectionEnded
4103 (
4104 const std::string& name,
4105 std::size_t prevSuccesses,
4106 std::size_t prevFailures
4107 )
4108 {
4109 m_runningTest->endSection( name );
4110 m_reporter->EndSection( name, m_successes - prevSuccesses, m_failures - prevFailures );
4111 }
4112
4113 ///////////////////////////////////////////////////////////////////////////
4114 virtual void pushScopedInfo
4115 (
4116 ScopedInfo* scopedInfo
4117 )
4118 {
4119 m_scopedInfos.push_back( scopedInfo );
4120 }
4121
4122 ///////////////////////////////////////////////////////////////////////////
4123 virtual void popScopedInfo
4124 (
4125 ScopedInfo* scopedInfo
4126 )
4127 {
4128 if( m_scopedInfos.back() == scopedInfo )
4129 m_scopedInfos.pop_back();
4130 }
4131
4132 ///////////////////////////////////////////////////////////////////////////
4133 virtual bool shouldDebugBreak
4134 ()
4135 const
4136 {
4137 return m_config.shouldDebugBreak();
4138 }
4139
4140 ///////////////////////////////////////////////////////////////////////////
4141 virtual std::string getCurrentTestName
4142 ()
4143 const
4144 {
4145 return m_runningTest
4146 ? m_runningTest->getTestCaseInfo().getName()
4147 : "";
4148 }
4149
4150 private:
4151
4152 ///////////////////////////////////////////////////////////////////////////
4153 ResultAction::Value actOnCurrentResult
4154 ()
4155 {
4156 testEnded( m_currentResult );
4157
4158 bool ok = m_currentResult.ok();
4159 m_currentResult = MutableResultInfo();
4160 if( ok )
4161 return ResultAction::None;
4162 else if( shouldDebugBreak() )
4163 return ResultAction::DebugFailed;
4164 else
4165 return ResultAction::Failed;
4166 }
4167
4168 ///////////////////////////////////////////////////////////////////////////
4169 void runCurrentTest
4170 (
4171 std::string& redirectedCout,
4172 std::string& redirectedCerr
4173 )
4174 {
4175 try
4176 {
4177 m_runningTest->reset();
4178 StreamRedirect coutRedir( std::cout, redirectedCout );
4179 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
4180 m_runningTest->getTestCaseInfo().invoke();
4181 m_runningTest->ranToCompletion();
4182 }
4183 catch( TestFailureException& )
4184 {
4185 // This just means the test was aborted due to failure
4186 }
4187 catch( std::exception& ex )
4188 {
4189 acceptMessage( ex.what() );
4190 acceptResult( ResultWas::ThrewException );
4191 }
4192 catch( std::string& msg )
4193 {
4194 acceptMessage( msg );
4195 acceptResult( ResultWas::ThrewException );
4196 }
4197 catch( const char* msg )
4198 {
4199 acceptMessage( msg );
4200 acceptResult( ResultWas::ThrewException );
4201 }
4202 catch(...)
4203 {
4204 acceptMessage( Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() );
4205 acceptResult( ResultWas::ThrewException );
4206 }
4207 m_info.clear();
4208 }
4209
4210 private:
4211 RunningTest* m_runningTest;
4212 MutableResultInfo m_currentResult;
4213
4214 const Config& m_config;
4215 std::size_t m_successes;
4216 std::size_t m_failures;
4217 IReporter* m_reporter;
4218 std::vector<ScopedInfo*> m_scopedInfos;
4219 std::vector<ResultInfo> m_info;
4220 IRunner* m_prevRunner;
4221 IResultCapture* m_prevResultCapture;
4222 };
4223}
4224
4225// #included from: catch_generators_impl.hpp
4226
4227/*
4228 * catch_generators_impl.hpp
4229 * Catch
4230 *
4231 * Created by Phil on 28/01/2011.
4232 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
4233 *
4234 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4235 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4236 *
4237 */
4238
4239#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
4240
4241
4242#include <vector>
4243#include <string>
4244#include <map>
4245
4246namespace Catch
4247{
4248 struct GeneratorInfo
4249 {
4250 ///////////////////////////////////////////////////////////////////////
4251 GeneratorInfo
4252 (
4253 std::size_t size
4254 )
4255 : m_size( size ),
4256 m_currentIndex( 0 )
4257 {
4258 }
4259
4260 ///////////////////////////////////////////////////////////////////////
4261 bool moveNext
4262 ()
4263 {
4264 if( ++m_currentIndex == m_size )
4265 {
4266 m_currentIndex = 0;
4267 return false;
4268 }
4269 return true;
4270 }
4271
4272 ///////////////////////////////////////////////////////////////////////
4273 std::size_t getCurrentIndex
4274 ()
4275 const
4276 {
4277 return m_currentIndex;
4278 }
4279
4280 std::size_t m_size;
4281 std::size_t m_currentIndex;
4282 };
4283
4284 ///////////////////////////////////////////////////////////////////////////
4285 ///////////////////////////////////////////////////////////////////////////
4286
4287 class GeneratorsForTest
4288 {
4289
4290 public:
4291 ///////////////////////////////////////////////////////////////////////
4292 ~GeneratorsForTest
4293 ()
4294 {
4295 deleteAll( m_generatorsInOrder );
4296 }
4297
4298 ///////////////////////////////////////////////////////////////////////
4299 GeneratorInfo& getGeneratorInfo
4300 (
4301 const std::string& fileInfo,
4302 std::size_t size
4303 )
4304 {
4305 std::map<std::string, GeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
4306 if( it == m_generatorsByName.end() )
4307 {
4308 GeneratorInfo* info = new GeneratorInfo( size );
4309 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
4310 m_generatorsInOrder.push_back( info );
4311 return *info;
4312 }
4313 return *it->second;
4314 }
4315
4316 ///////////////////////////////////////////////////////////////////////
4317 bool moveNext
4318 ()
4319 {
4320 std::vector<GeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
4321 std::vector<GeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
4322 for(; it != itEnd; ++it )
4323 {
4324 if( (*it)->moveNext() )
4325 return true;
4326 }
4327 return false;
4328 }
4329
4330 private:
4331 std::map<std::string, GeneratorInfo*> m_generatorsByName;
4332 std::vector<GeneratorInfo*> m_generatorsInOrder;
4333 };
4334
4335} // end namespace Catch
4336
4337#define INTERNAL_CATCH_LINESTR2( line ) #line
4338#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
4339
4340#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
4341
4342// #included from: catch_stream.hpp
4343
4344/*
4345 * catch_stream.hpp
4346 * Catch
4347 *
4348 * Created by Phil on 17/01/2011.
4349 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
4350 *
4351 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4352 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4353 *
4354 */
4355
4356#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
4357
4358#include <stdexcept>
4359#include <cstdio>
4360
4361namespace Catch
4362{
4363 template<typename WriterF, size_t bufferSize=256>
4364 class StreamBufImpl : public StreamBufBase
4365 {
4366 char data[bufferSize];
4367 WriterF m_writer;
4368
4369 public:
4370 ///////////////////////////////////////////////////////////////////////
4371 StreamBufImpl
4372 ()
4373 {
4374 setp( data, data + sizeof(data) );
4375 }
4376
4377 ///////////////////////////////////////////////////////////////////////
4378 ~StreamBufImpl
4379 ()
4380 {
4381 sync();
4382 }
4383
4384 private:
4385 ///////////////////////////////////////////////////////////////////////
4386 int overflow
4387 (
4388 int c
4389 )
4390 {
4391 sync();
4392
4393 if( c != EOF )
4394 {
4395 if( pbase() == epptr() )
4396 m_writer( std::string( 1, static_cast<char>( c ) ) );
4397 else
4398 sputc( static_cast<char>( c ) );
4399 }
4400 return 0;
4401 }
4402
4403 ///////////////////////////////////////////////////////////////////////
4404 int sync
4405 ()
4406 {
4407 if( pbase() != pptr() )
4408 {
4409 m_writer( std::string( pbase(), pptr() - pbase() ) );
4410 setp( pbase(), epptr() );
4411 }
4412 return 0;
4413 }
4414 };
4415
4416 ///////////////////////////////////////////////////////////////////////////
4417 ///////////////////////////////////////////////////////////////////////////
4418
4419 struct OutputDebugWriter
4420 {
4421 ///////////////////////////////////////////////////////////////////////
4422 void operator()
4423 (
4424 const std::string &str
4425 )
4426 {
4427 writeToDebugConsole( str );
4428 }
4429 };
4430}
4431
4432
4433namespace Catch
4434{
4435 ///////////////////////////////////////////////////////////////////////////
4436 Hub::Hub
4437 ()
4438 : m_reporterRegistry( new ReporterRegistry ),
4439 m_testCaseRegistry( new TestRegistry ),
4440 m_exceptionTranslatorRegistry( new ExceptionTranslatorRegistry )
4441 {
4442 }
4443
4444 ///////////////////////////////////////////////////////////////////////////
4445 Hub& Hub::me
4446 ()
4447 {
4448 static Hub hub;
4449 return hub;
4450 }
4451
4452 ///////////////////////////////////////////////////////////////////////////
4453 void Hub::setRunner( IRunner* runner )
4454 {
4455 me().m_runner = runner;
4456 }
4457 ///////////////////////////////////////////////////////////////////////////
4458 void Hub::setResultCapture( IResultCapture* resultCapture )
4459 {
4460 me().m_resultCapture = resultCapture;
4461 }
4462
4463 ///////////////////////////////////////////////////////////////////////////
4464 IResultCapture& Hub::getResultCapture
4465 ()
4466 {
4467 return *me().m_resultCapture;
4468 }
4469
4470 ///////////////////////////////////////////////////////////////////////////
4471 IRunner& Hub::getRunner
4472 ()
4473 {
4474 return *me().m_runner;
4475 }
4476
4477 ///////////////////////////////////////////////////////////////////////////
4478 IReporterRegistry& Hub::getReporterRegistry
4479 ()
4480 {
4481 return *me().m_reporterRegistry.get();
4482 }
4483
4484 ///////////////////////////////////////////////////////////////////////////
4485 ITestCaseRegistry& Hub::getTestCaseRegistry
4486 ()
4487 {
4488 return *me().m_testCaseRegistry.get();
4489 }
4490
4491 ///////////////////////////////////////////////////////////////////////////
4492 IExceptionTranslatorRegistry& Hub::getExceptionTranslatorRegistry
4493 ()
4494 {
4495 return *me().m_exceptionTranslatorRegistry.get();
4496 }
4497
4498 ///////////////////////////////////////////////////////////////////////////
4499 std::streambuf* Hub::createStreamBuf
4500 (
4501 const std::string& streamName
4502 )
4503 {
4504 if( streamName == "stdout" ) return std::cout.rdbuf();
4505 if( streamName == "stderr" ) return std::cerr.rdbuf();
4506 if( streamName == "debug" ) return new StreamBufImpl<OutputDebugWriter>;
4507
4508 throw std::domain_error( "Unknown stream: " + streamName );
4509 }
4510
4511 ///////////////////////////////////////////////////////////////////////////
4512 GeneratorsForTest* Hub::findGeneratorsForCurrentTest
4513 ()
4514 {
4515 std::string testName = getResultCapture().getCurrentTestName();
4516
4517 std::map<std::string, GeneratorsForTest*>::const_iterator it =
4518 m_generatorsByTestName.find( testName );
4519 return it != m_generatorsByTestName.end()
4520 ? it->second
4521 : NULL;
4522 }
4523 ///////////////////////////////////////////////////////////////////////////
4524 GeneratorsForTest& Hub::getGeneratorsForCurrentTest
4525 ()
4526 {
4527 GeneratorsForTest* generators = findGeneratorsForCurrentTest();
4528 if( !generators )
4529 {
4530 std::string testName = getResultCapture().getCurrentTestName();
4531 generators = new GeneratorsForTest();
4532 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
4533 }
4534 return *generators;
4535 }
4536
4537 ///////////////////////////////////////////////////////////////////////////
4538 size_t Hub::getGeneratorIndex
4539 (
4540 const std::string& fileInfo,
4541 size_t totalSize
4542 )
4543 {
4544 return me().getGeneratorsForCurrentTest()
4545 .getGeneratorInfo( fileInfo, totalSize )
4546 .getCurrentIndex();
4547 }
4548
4549 ///////////////////////////////////////////////////////////////////////////
4550 bool Hub::advanceGeneratorsForCurrentTest
4551 ()
4552 {
4553 GeneratorsForTest* generators = me().findGeneratorsForCurrentTest();
4554 return generators && generators->moveNext();
4555 }
4556}
4557
4558// #included from: internal/catch_commandline.hpp
4559
4560/*
4561 * catch_commandline.hpp
4562 * Catch
4563 *
4564 * Created by Phil on 02/11/2010.
4565 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
4566 *
4567 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4568 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4569 *
4570 */
4571
4572#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
4573
4574
4575namespace Catch
4576{
4577 // !TBD: This could be refactored to be more "declarative"
4578 // have a table up front that relates the mode, option strings, # arguments, names of arguments
4579 // - may not be worth it at this scale
4580
4581 // -l, --list tests [xml] lists available tests (optionally in xml)
4582 // -l, --list reporters [xml] lists available reports (optionally in xml)
4583 // -l, --list all [xml] lists available tests and reports (optionally in xml)
4584 // -t, --test "testspec" ["testspec", ...]
4585 // -r, --reporter <type>
4586 // -o, --out filename to write to
4587 // -s, --success report successful cases too
4588 // -b, --break breaks into debugger on test failure
4589 // -n, --name specifies an optional name for the test run
4590 class ArgParser : NonCopyable
4591 {
4592 enum Mode
4593 {
4594 modeNone,
4595 modeList,
4596 modeTest,
4597 modeReport,
4598 modeOutput,
4599 modeSuccess,
4600 modeBreak,
4601 modeName,
4602 modeHelp,
4603
4604 modeError
4605 };
4606
4607 public:
4608 ///////////////////////////////////////////////////////////////////////
4609 ArgParser
4610 (
4611 int argc,
4612 char * const argv[],
4613 Config& config
4614 )
4615 : m_mode( modeNone ),
4616 m_config( config )
4617 {
4618 for( int i=1; i < argc; ++i )
4619 {
4620 if( argv[i][0] == '-' )
4621 {
4622 std::string cmd = ( argv[i] );
4623 if( cmd == "-l" || cmd == "--list" )
4624 changeMode( cmd, modeList );
4625 else if( cmd == "-t" || cmd == "--test" )
4626 changeMode( cmd, modeTest );
4627 else if( cmd == "-r" || cmd == "--reporter" )
4628 changeMode( cmd, modeReport );
4629 else if( cmd == "-o" || cmd == "--out" )
4630 changeMode( cmd, modeOutput );
4631 else if( cmd == "-s" || cmd == "--success" )
4632 changeMode( cmd, modeSuccess );
4633 else if( cmd == "-b" || cmd == "--break" )
4634 changeMode( cmd, modeBreak );
4635 else if( cmd == "-n" || cmd == "--name" )
4636 changeMode( cmd, modeName );
4637 else if( cmd == "-h" || cmd == "-?" || cmd == "--help" )
4638 changeMode( cmd, modeHelp );
4639 }
4640 else
4641 {
4642 m_args.push_back( argv[i] );
4643 }
4644 if( m_mode == modeError )
4645 return;
4646 }
4647 changeMode( "", modeNone );
4648 }
4649
4650 private:
4651 ///////////////////////////////////////////////////////////////////////
4652 std::string argsAsString
4653 ()
4654 {
4655 std::ostringstream oss;
4656 std::vector<std::string>::const_iterator it = m_args.begin();
4657 std::vector<std::string>::const_iterator itEnd = m_args.end();
4658 for( bool first = true; it != itEnd; ++it, first = false )
4659 {
4660 if( !first )
4661 oss << " ";
4662 oss << *it;
4663 }
4664 return oss.str();
4665 }
4666
4667 ///////////////////////////////////////////////////////////////////////
4668 void changeMode
4669 (
4670 const std::string& cmd,
4671 Mode mode
4672 )
4673 {
4674 m_command = cmd;
4675 switch( m_mode )
4676 {
4677 case modeNone:
4678 if( m_args.size() > 0 )
4679 return setErrorMode( "Unexpected arguments before " + m_command + ": " + argsAsString() );
4680 break;
4681 case modeList:
4682 if( m_args.size() > 2 )
4683 {
4684 return setErrorMode( m_command + " expected upto 2 arguments but recieved: " + argsAsString() );
4685 }
4686 else
4687 {
4688 Config::List::What listSpec = Config::List::All;
4689 if( m_args.size() >= 1 )
4690 {
4691 if( m_args[0] == "tests" )
4692 listSpec = Config::List::Tests;
4693 else if( m_args[0] == "reporters" )
4694 listSpec = Config::List::Reports;
4695 else
4696 return setErrorMode( m_command + " expected [tests] or [reporters] but recieved: [" + m_args[0] + "]" );
4697 }
4698 if( m_args.size() >= 2 )
4699 {
4700 if( m_args[1] == "xml" )
4701 listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsXml );
4702 else if( m_args[1] == "text" )
4703 listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsText );
4704 else
4705 return setErrorMode( m_command + " expected [xml] or [text] but recieved: [" + m_args[1] + "]" );
4706 }
4707 m_config.setListSpec( static_cast<Config::List::What>( m_config.getListSpec() | listSpec ) );
4708 }
4709 break;
4710 case modeTest:
4711 if( m_args.size() == 0 )
4712 return setErrorMode( m_command + " expected at least 1 argument but recieved none" );
4713 {
4714 std::vector<std::string>::const_iterator it = m_args.begin();
4715 std::vector<std::string>::const_iterator itEnd = m_args.end();
4716 for(; it != itEnd; ++it )
4717 m_config.addTestSpec( *it );
4718 }
4719 break;
4720 case modeReport:
4721 if( m_args.size() != 1 )
4722 return setErrorMode( m_command + " expected one argument, recieved: " + argsAsString() );
4723 m_config.setReporter( m_args[0] );
4724 break;
4725 case modeOutput:
4726 if( m_args.size() == 0 )
4727 return setErrorMode( m_command + " expected filename" );
4728 if( m_args[0][0] == '%' )
4729 m_config.useStream( m_args[0].substr( 1 ) );
4730 else
4731 m_config.setFilename( m_args[0] );
4732 break;
4733 case modeSuccess:
4734 if( m_args.size() != 0 )
4735 return setErrorMode( m_command + " does not accept arguments" );
4736 m_config.setIncludeWhat( Config::Include::SuccessfulResults );
4737 break;
4738 case modeBreak:
4739 if( m_args.size() != 0 )
4740 return setErrorMode( m_command + " does not accept arguments" );
4741 m_config.setShouldDebugBreak( true );
4742 break;
4743 case modeName:
4744 if( m_args.size() != 1 )
4745 return setErrorMode( m_command + " requires exactly one argument (a name)" );
4746 m_config.setName( m_args[0] );
4747 break;
4748 case modeHelp:
4749 if( m_args.size() != 0 )
4750 return setErrorMode( m_command + " does not accept arguments" );
4751 m_config.setShowHelp( true );
4752 break;
4753 default:
4754 break;
4755 }
4756 m_args.clear();
4757 m_mode = mode;
4758 }
4759
4760 ///////////////////////////////////////////////////////////////////////
4761 void setErrorMode
4762 (
4763 const std::string& errorMessage
4764 )
4765 {
4766 m_mode = modeError;
4767 m_command = "";
4768 m_config.setError( errorMessage );
4769 }
4770
4771 private:
4772
4773 Mode m_mode;
4774 std::string m_command;
4775 std::vector<std::string> m_args;
4776 Config& m_config;
4777 };
4778
4779
4780} // end namespace Catch
4781
4782// #included from: internal/catch_list.hpp
4783
4784/*
4785 * catch_list.hpp
4786 * Catch
4787 *
4788 * Created by Phil on 5/11/2010.
4789 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
4790 *
4791 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4792 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4793 *
4794 */
4795
4796#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4797
4798#include <limits>
4799
4800namespace Catch
4801{
4802 ///////////////////////////////////////////////////////////////////////////
4803 inline int List
4804 (
4805 const Config& config
4806 )
4807 {
4808 if( config.listWhat() & Config::List::Reports )
4809 {
4810 std::cout << "Available reports:\n";
4811 IReporterRegistry::FactoryMap::const_iterator it = Hub::getReporterRegistry().getFactories().begin();
4812 IReporterRegistry::FactoryMap::const_iterator itEnd = Hub::getReporterRegistry().getFactories().end();
4813 for(; it != itEnd; ++it )
4814 {
4815 // !TBD: consider listAs()
4816 std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
4817 }
4818 std::cout << std::endl;
4819 }
4820 if( config.listWhat() & Config::List::Tests )
4821 {
4822 std::cout << "Available tests:\n";
4823 std::vector<TestCaseInfo>::const_iterator it = Hub::getTestCaseRegistry().getAllTests().begin();
4824 std::vector<TestCaseInfo>::const_iterator itEnd = Hub::getTestCaseRegistry().getAllTests().end();
4825 for(; it != itEnd; ++it )
4826 {
4827 // !TBD: consider listAs()
4828 std::cout << "\t" << it->getName() << "\n\t\t '" << it->getDescription() << "'\n";
4829 }
4830 std::cout << std::endl;
4831 }
4832 if( ( config.listWhat() & Config::List::All ) == 0 )
4833 {
4834 std::cerr << "Unknown list type" << std::endl;
4835 return (std::numeric_limits<int>::max)();
4836 }
4837
4838 if( config.getReporter() )
4839 {
4840 std::cerr << "Reporters ignored when listing" << std::endl;
4841 }
4842 if( !config.testsSpecified() )
4843 {
4844 std::cerr << "Test specs ignored when listing" << std::endl;
4845 }
4846 return 0;
4847
4848 }
4849
4850} // end namespace Catch
4851
4852// #included from: reporters/catch_reporter_basic.hpp
4853
4854/*
4855 * catch_reporter_basic.hpp
4856 * Catch
4857 *
4858 * Created by Phil on 28/10/2010.
4859 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
4860 *
4861 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4862 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4863 *
4864 */
4865#define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
4866
Phil Nashf721a962011-06-07 14:13:57 +01004867// #included from: ../internal/catch_reporter_registrars.hpp
Phil Nash89d1e6c2011-05-24 08:23:02 +01004868
4869/*
4870 * catch_reporter_registrars.hpp
4871 * Test
4872 *
4873 * Created by Phil on 31/12/2010.
4874 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
4875 *
4876 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4877 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4878 *
4879 */
4880#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
4881
4882
4883namespace Catch
4884{
4885 template<typename T>
4886 class ReporterRegistrar
4887 {
4888 class ReporterFactory : public IReporterFactory
4889 {
4890 ///////////////////////////////////////////////////////////////////
4891 virtual IReporter* create
4892 (
4893 const IReporterConfig& config
4894 )
4895 const
4896 {
4897 return new T( config );
4898 }
4899 ///////////////////////////////////////////////////////////////////
4900 virtual std::string getDescription
4901 ()
4902 const
4903 {
4904 return T::getDescription();
4905 }
4906 };
4907
4908 public:
4909
4910 ///////////////////////////////////////////////////////////////////////
4911 ReporterRegistrar
4912 (
4913 const std::string& name
4914 )
4915 {
4916 Hub::getReporterRegistry().registerReporter( name, new ReporterFactory() );
4917 }
4918 };
4919}
4920
4921///////////////////////////////////////////////////////////////////////////////
4922#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
4923 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
4924
4925
4926namespace Catch
4927{
4928 class BasicReporter : public IReporter
4929 {
4930 struct SpanInfo
4931 {
4932 SpanInfo()
4933 : emitted( false )
4934 {}
4935
4936 SpanInfo( const std::string& spanName )
4937 : name( spanName ),
4938 emitted( false )
4939 {}
4940
4941 SpanInfo( const SpanInfo& other )
4942 : name( other.name ),
4943 emitted( other.emitted )
4944 {}
4945
4946 std::string name;
4947 bool emitted;
4948 };
4949
4950 public:
4951 ///////////////////////////////////////////////////////////////////////////
4952 BasicReporter
4953 (
4954 const IReporterConfig& config
4955 )
4956 : m_config( config )
4957 {
4958 }
4959
4960 ///////////////////////////////////////////////////////////////////////////
4961 static std::string getDescription
4962 ()
4963 {
4964 return "Reports test results as lines of text";
4965 }
4966
4967 private:
4968
4969 ///////////////////////////////////////////////////////////////////////////
4970 void ReportCounts
4971 (
4972 std::size_t succeeded,
4973 std::size_t failed
4974 )
4975 {
4976 if( failed + succeeded == 0 )
4977 m_config.stream() << "No tests ran";
4978 else if( failed == 0 )
4979 m_config.stream() << "All " << succeeded << " test(s) succeeded";
4980 else if( succeeded == 0 )
4981 m_config.stream() << "All " << failed << " test(s) failed";
4982 else
4983 m_config.stream() << succeeded << " test(s) passed but " << failed << " test(s) failed";
4984 }
4985
4986 private: // IReporter
4987
4988 ///////////////////////////////////////////////////////////////////////////
4989 virtual void StartTesting
4990 ()
4991 {
4992 m_testingSpan = SpanInfo();
4993 }
4994
4995 ///////////////////////////////////////////////////////////////////////////
4996 virtual void EndTesting
4997 (
4998 std::size_t succeeded,
4999 std::size_t failed
5000 )
5001 {
5002 // Output the overall test results even if "Started Testing" was not emitted
5003 m_config.stream() << "[Testing completed. ";
5004 ReportCounts( succeeded, failed );
5005 m_config.stream() << "]\n" << std::endl;
5006 }
5007
5008 ///////////////////////////////////////////////////////////////////////////
5009 virtual void StartGroup
5010 (
5011 const std::string& groupName
5012 )
5013 {
5014 m_groupSpan = groupName;
5015 }
5016
5017 ///////////////////////////////////////////////////////////////////////////
5018 virtual void EndGroup
5019 (
5020 const std::string& groupName,
5021 std::size_t succeeded,
5022 std::size_t failed
5023 )
5024 {
5025 if( m_groupSpan.emitted && !groupName.empty() )
5026 {
5027 m_config.stream() << "[End of group: '" << groupName << "'. ";
5028 ReportCounts( succeeded, failed );
5029 m_config.stream() << "]\n" << std::endl;
5030 m_groupSpan = SpanInfo();
5031 }
5032 }
5033
5034 ///////////////////////////////////////////////////////////////////////////
5035 virtual void StartTestCase
5036 (
5037 const TestCaseInfo& testInfo
5038 )
5039 {
5040 m_testSpan = testInfo.getName();
5041 }
5042
5043 ///////////////////////////////////////////////////////////////////////////
5044 virtual void StartSection
5045 (
5046 const std::string& sectionName,
5047 const std::string /*description*/
5048 )
5049 {
5050 m_sectionSpans.push_back( SpanInfo( sectionName ) );
5051 }
5052
5053 ///////////////////////////////////////////////////////////////////////////
5054 virtual void EndSection
5055 (
5056 const std::string& sectionName,
5057 std::size_t succeeded,
5058 std::size_t failed
5059 )
5060 {
5061 SpanInfo& sectionSpan = m_sectionSpans.back();
5062 if( sectionSpan.emitted && !sectionSpan.name.empty() )
5063 {
5064 m_config.stream() << "[End of section: '" << sectionName << "'. ";
5065 ReportCounts( succeeded, failed );
5066 m_config.stream() << "]\n" << std::endl;
5067 }
5068 m_sectionSpans.pop_back();
5069 }
5070
5071 ///////////////////////////////////////////////////////////////////////////
5072 virtual void Result
5073 (
5074 const ResultInfo& resultInfo
5075 )
5076 {
5077 if( !m_config.includeSuccessfulResults() && resultInfo.getResultType() == ResultWas::Ok )
5078 return;
5079
5080 StartSpansLazily();
5081
5082 if( !resultInfo.getFilename().empty() )
5083#ifndef __GNUG__
5084 m_config.stream() << resultInfo.getFilename() << "(" << resultInfo.getLine() << "): ";
5085#else
5086 m_config.stream() << resultInfo.getFilename() << ":" << resultInfo.getLine() << ": ";
5087#endif
5088
5089 if( resultInfo.hasExpression() )
5090 {
5091 m_config.stream() << resultInfo.getExpression();
5092 if( resultInfo.ok() )
5093 m_config.stream() << " succeeded";
5094 else
5095 m_config.stream() << " failed";
5096 }
5097 switch( resultInfo.getResultType() )
5098 {
5099 case ResultWas::ThrewException:
5100 if( resultInfo.hasExpression() )
5101 m_config.stream() << " with unexpected";
5102 else
5103 m_config.stream() << "Unexpected";
5104 m_config.stream() << " exception with message: '" << resultInfo.getMessage() << "'";
5105 break;
5106 case ResultWas::DidntThrowException:
5107 if( resultInfo.hasExpression() )
5108 m_config.stream() << " because no exception was thrown where one was expected";
5109 else
5110 m_config.stream() << "No exception thrown where one was expected";
5111 break;
5112 case ResultWas::Info:
5113 streamVariableLengthText( "info", resultInfo.getMessage() );
5114 break;
5115 case ResultWas::Warning:
5116 m_config.stream() << "warning:\n'" << resultInfo.getMessage() << "'";
5117 break;
5118 case ResultWas::ExplicitFailure:
5119 m_config.stream() << "failed with message: '" << resultInfo.getMessage() << "'";
5120 break;
5121 default:
5122 if( !resultInfo.hasExpression() )
5123 {
5124 if( resultInfo.ok() )
5125 m_config.stream() << " succeeded";
5126 else
5127 m_config.stream() << " failed";
5128 }
5129 break;
5130 }
5131
5132 if( resultInfo.hasExpression() )
5133 {
5134 m_config.stream() << " for: " << resultInfo.getExpandedExpression();
5135 }
5136 m_config.stream() << std::endl;
5137 }
5138
5139 ///////////////////////////////////////////////////////////////////////////
5140 virtual void EndTestCase
5141 (
5142 const TestCaseInfo& testInfo,
5143 std::size_t succeeded,
5144 std::size_t failed,
5145 const std::string& stdOut,
5146 const std::string& stdErr
5147 )
5148 {
5149 if( !stdOut.empty() )
5150 {
5151 StartSpansLazily();
5152 streamVariableLengthText( "stdout", stdOut );
5153 }
5154
5155 if( !stdErr.empty() )
5156 {
5157 StartSpansLazily();
5158 streamVariableLengthText( "stderr", stdErr );
5159 }
5160
5161 if( m_testSpan.emitted )
5162 {
5163 m_config.stream() << "[Finished: " << testInfo.getName() << " ";
5164 ReportCounts( succeeded, failed );
5165 m_config.stream() << "]" << std::endl;
5166 }
5167 }
5168
5169 private: // helpers
5170
5171 ///////////////////////////////////////////////////////////////////////////
5172 void StartSpansLazily()
5173 {
5174 if( !m_testingSpan.emitted )
5175 {
5176 if( m_config.getName().empty() )
5177 m_config.stream() << "[Started testing]" << std::endl;
5178 else
5179 m_config.stream() << "[Started testing: " << m_config.getName() << "]" << std::endl;
5180 m_testingSpan.emitted = true;
5181 }
5182
5183 if( !m_groupSpan.emitted && !m_groupSpan.name.empty() )
5184 {
5185 m_config.stream() << "[Started group: '" << m_groupSpan.name << "']" << std::endl;
5186 m_groupSpan.emitted = true;
5187 }
5188
5189 if( !m_testSpan.emitted )
5190 {
5191 m_config.stream() << std::endl << "[Running: " << m_testSpan.name << "]" << std::endl;
5192 m_testSpan.emitted = true;
5193 }
5194
5195 if( !m_sectionSpans.empty() )
5196 {
5197 SpanInfo& sectionSpan = m_sectionSpans.back();
5198 if( !sectionSpan.emitted && !sectionSpan.name.empty() )
5199 {
5200 if( m_firstSectionInTestCase )
5201 {
5202 m_config.stream() << "\n";
5203 m_firstSectionInTestCase = false;
5204 }
5205 std::vector<SpanInfo>::iterator it = m_sectionSpans.begin();
5206 std::vector<SpanInfo>::iterator itEnd = m_sectionSpans.end();
5207 for(; it != itEnd; ++it )
5208 {
5209 SpanInfo& prevSpan = *it;
5210 if( !prevSpan.emitted && !prevSpan.name.empty() )
5211 {
5212 m_config.stream() << "[Started section: '" << prevSpan.name << "']" << std::endl;
5213 prevSpan.emitted = true;
5214 }
5215 }
5216 }
5217 }
5218 }
5219
5220 ///////////////////////////////////////////////////////////////////////////
5221 void streamVariableLengthText
5222 (
5223 const std::string& prefix,
5224 const std::string& text
5225 )
5226 {
5227 std::string trimmed = trim( text );
5228 if( trimmed.find_first_of( "\r\n" ) == std::string::npos )
5229 {
5230 m_config.stream() << "[" << prefix << ": " << trimmed << "]\n";
5231 }
5232 else
5233 {
5234 m_config.stream() << "\n[" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed
5235 << "\n[end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<<\n";
5236 }
5237 }
5238
5239 private:
5240 const IReporterConfig& m_config;
5241 bool m_firstSectionInTestCase;
5242
5243 SpanInfo m_testingSpan;
5244 SpanInfo m_groupSpan;
5245 SpanInfo m_testSpan;
5246 std::vector<SpanInfo> m_sectionSpans;
5247 };
5248
5249 INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
5250
5251} // end namespace Catch
5252
5253// #included from: reporters/catch_reporter_xml.hpp
5254
5255/*
5256 * catch_reporter_xml.hpp
5257 * Catch
5258 *
5259 * Created by Phil on 28/10/2010.
5260 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
5261 *
5262 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5263 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5264 *
5265 */
5266#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
5267
Phil Nashf721a962011-06-07 14:13:57 +01005268// #included from: ../internal/catch_xmlwriter.hpp
Phil Nash89d1e6c2011-05-24 08:23:02 +01005269
5270/*
5271 * catch_xmlwriter.hpp
5272 * Catch
5273 *
5274 * Created by Phil on 09/12/2010.
5275 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
5276 *
5277 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5278 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5279 */
5280#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
5281
5282#include <sstream>
5283#include <string>
5284#include <vector>
5285
5286namespace Catch
5287{
5288 class XmlWriter
5289 {
5290 public:
5291
5292 class ScopedElement
5293 {
5294 public:
5295 ///////////////////////////////////////////////////////////////////
5296 ScopedElement
5297 (
5298 XmlWriter* writer
5299 )
5300 : m_writer( writer )
5301 {
5302 }
5303
5304 ///////////////////////////////////////////////////////////////////
5305 ScopedElement
5306 (
5307 const ScopedElement& other
5308 )
5309 : m_writer( other.m_writer )
5310 {
5311 other.m_writer = NULL;
5312 }
5313
5314 ///////////////////////////////////////////////////////////////////
5315 ~ScopedElement
5316 ()
5317 {
5318 if( m_writer )
5319 m_writer->endElement();
5320 }
5321
5322 ///////////////////////////////////////////////////////////////////
5323 ScopedElement& writeText
5324 (
5325 const std::string& text
5326 )
5327 {
5328 m_writer->writeText( text );
5329 return *this;
5330 }
5331
5332 ///////////////////////////////////////////////////////////////////
5333 template<typename T>
5334 ScopedElement& writeAttribute
5335 (
5336 const std::string& name,
5337 const T& attribute
5338 )
5339 {
5340 m_writer->writeAttribute( name, attribute );
5341 return *this;
5342 }
5343
5344 private:
5345 mutable XmlWriter* m_writer;
5346 };
5347
5348 ///////////////////////////////////////////////////////////////////////
5349 XmlWriter
5350 ()
5351 : m_tagIsOpen( false ),
5352 m_needsNewline( false ),
5353 m_os( &std::cout )
5354 {
5355 }
5356
5357 ///////////////////////////////////////////////////////////////////////
5358 XmlWriter
5359 (
5360 std::ostream& os
5361 )
5362 : m_tagIsOpen( false ),
5363 m_needsNewline( false ),
5364 m_os( &os )
5365 {
5366 }
5367
5368 ///////////////////////////////////////////////////////////////////////
5369 ~XmlWriter
5370 ()
5371 {
5372 while( !m_tags.empty() )
5373 {
5374 endElement();
5375 }
5376 }
5377
5378 ///////////////////////////////////////////////////////////////////////
5379 XmlWriter& operator =
5380 (
5381 const XmlWriter& other
5382 )
5383 {
5384 XmlWriter temp( other );
5385 swap( temp );
5386 return *this;
5387 }
5388
5389 ///////////////////////////////////////////////////////////////////////
5390 void swap
5391 (
5392 XmlWriter& other
5393 )
5394 {
5395 std::swap( m_tagIsOpen, other.m_tagIsOpen );
5396 std::swap( m_needsNewline, other.m_needsNewline );
5397 std::swap( m_tags, other.m_tags );
5398 std::swap( m_indent, other.m_indent );
5399 std::swap( m_os, other.m_os );
5400 }
5401
5402 ///////////////////////////////////////////////////////////////////////
5403 XmlWriter& startElement
5404 (
5405 const std::string& name
5406 )
5407 {
5408 ensureTagClosed();
5409 newlineIfNecessary();
5410 stream() << m_indent << "<" << name;
5411 m_tags.push_back( name );
5412 m_indent += " ";
5413 m_tagIsOpen = true;
5414 return *this;
5415 }
5416
5417 ///////////////////////////////////////////////////////////////////////
5418 ScopedElement scopedElement
5419 (
5420 const std::string& name
5421 )
5422 {
5423 ScopedElement scoped( this );
5424 startElement( name );
5425 return scoped;
5426 }
5427
5428 ///////////////////////////////////////////////////////////////////////
5429 XmlWriter& endElement
5430 ()
5431 {
5432 newlineIfNecessary();
5433 m_indent = m_indent.substr( 0, m_indent.size()-2 );
5434 if( m_tagIsOpen )
5435 {
5436 stream() << "/>\n";
5437 m_tagIsOpen = false;
5438 }
5439 else
5440 {
5441 stream() << m_indent << "</" << m_tags.back() << ">\n";
5442 }
5443 m_tags.pop_back();
5444 return *this;
5445 }
5446
5447 ///////////////////////////////////////////////////////////////////////
5448 XmlWriter& writeAttribute
5449 (
5450 const std::string& name,
5451 const std::string& attribute
5452 )
5453 {
5454 if( !name.empty() && !attribute.empty() )
5455 {
5456 stream() << " " << name << "=\"";
5457 writeEncodedText( attribute );
5458 stream() << "\"";
5459 }
5460 return *this;
5461 }
5462
5463 ///////////////////////////////////////////////////////////////////////
5464 XmlWriter& writeAttribute
5465 (
5466 const std::string& name,
5467 bool attribute
5468 )
5469 {
5470 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
5471 return *this;
5472 }
5473
5474 ///////////////////////////////////////////////////////////////////////
5475 template<typename T>
5476 XmlWriter& writeAttribute
5477 (
5478 const std::string& name,
5479 const T& attribute
5480 )
5481 {
5482 if( !name.empty() )
5483 {
5484 stream() << " " << name << "=\"" << attribute << "\"";
5485 }
5486 return *this;
5487 }
5488
5489 ///////////////////////////////////////////////////////////////////////
5490 XmlWriter& writeText
5491 (
5492 const std::string& text
5493 )
5494 {
5495 if( !text.empty() )
5496 {
5497 bool tagWasOpen = m_tagIsOpen;
5498 ensureTagClosed();
5499 if( tagWasOpen )
5500 stream() << m_indent;
5501 writeEncodedText( text );
5502 m_needsNewline = true;
5503 }
5504 return *this;
5505 }
5506
5507 ///////////////////////////////////////////////////////////////////////
5508 XmlWriter& writeComment
5509 (
5510 const std::string& text
5511 )
5512 {
5513 ensureTagClosed();
5514 stream() << m_indent << "<!--" << text << "-->";
5515 m_needsNewline = true;
5516 return *this;
5517 }
5518
5519 ///////////////////////////////////////////////////////////////////////
5520 XmlWriter& writeBlankLine
5521 ()
5522 {
5523 ensureTagClosed();
5524 stream() << "\n";
5525 return *this;
5526 }
5527
5528 private:
5529
5530 ///////////////////////////////////////////////////////////////////////
5531 std::ostream& stream
5532 ()
5533 {
5534 return *m_os;
5535 }
5536
5537 ///////////////////////////////////////////////////////////////////////
5538 void ensureTagClosed
5539 ()
5540 {
5541 if( m_tagIsOpen )
5542 {
5543 stream() << ">\n";
5544 m_tagIsOpen = false;
5545 }
5546 }
5547
5548 ///////////////////////////////////////////////////////////////////////
5549 void newlineIfNecessary
5550 ()
5551 {
5552 if( m_needsNewline )
5553 {
5554 stream() << "\n";
5555 m_needsNewline = false;
5556 }
5557 }
5558
5559 ///////////////////////////////////////////////////////////////////////
5560 void writeEncodedText
5561 (
5562 const std::string& text
5563 )
5564 {
5565 // !TBD finish this
5566 if( !findReplaceableString( text, "<", "&lt;" ) &&
5567 !findReplaceableString( text, "&", "&amp;" ) &&
5568 !findReplaceableString( text, "\"", "&quote;" ) )
5569 {
5570 stream() << text;
5571 }
5572 }
5573
5574 ///////////////////////////////////////////////////////////////////////
5575 bool findReplaceableString
5576 (
5577 const std::string& text,
5578 const std::string& replaceWhat,
5579 const std::string& replaceWith
5580 )
5581 {
5582 std::string::size_type pos = text.find_first_of( replaceWhat );
5583 if( pos != std::string::npos )
5584 {
5585 stream() << text.substr( 0, pos ) << replaceWith;
5586 writeEncodedText( text.substr( pos+1 ) );
5587 return true;
5588 }
5589 return false;
5590 }
5591
5592 bool m_tagIsOpen;
5593 bool m_needsNewline;
5594 std::vector<std::string> m_tags;
5595 std::string m_indent;
5596 std::ostream* m_os;
5597 };
5598
5599}
5600
5601namespace Catch
5602{
5603 class XmlReporter : public Catch::IReporter
5604 {
5605 public:
5606 ///////////////////////////////////////////////////////////////////////////
5607 XmlReporter
5608 (
5609 const IReporterConfig& config
5610 )
5611 : m_config( config )
5612 {
5613 }
5614
5615 ///////////////////////////////////////////////////////////////////////////
5616 static std::string getDescription
5617 ()
5618 {
5619 return "Reports test results as an XML document";
5620 }
5621
5622 private: // IReporter
5623
5624 ///////////////////////////////////////////////////////////////////////////
5625 virtual void StartTesting
5626 ()
5627 {
5628 m_xml = XmlWriter( m_config.stream() );
5629 m_xml.startElement( "Catch" );
5630 if( !m_config.getName().empty() )
5631 m_xml.writeAttribute( "name", m_config.getName() );
5632 }
5633
5634 ///////////////////////////////////////////////////////////////////////////
5635 virtual void EndTesting
5636 (
5637 std::size_t succeeded,
5638 std::size_t failed
5639 )
5640 {
5641 m_xml.scopedElement( "OverallResults" )
5642 .writeAttribute( "successes", succeeded )
5643 .writeAttribute( "failures", failed );
5644 m_xml.endElement();
5645 }
5646
5647 ///////////////////////////////////////////////////////////////////////////
5648 virtual void StartGroup
5649 (
5650 const std::string& groupName
5651 )
5652 {
5653 m_xml.startElement( "Group" )
5654 .writeAttribute( "name", groupName );
5655 }
5656
5657 ///////////////////////////////////////////////////////////////////////////
5658 virtual void EndGroup
5659 (
5660 const std::string& /*groupName*/,
5661 std::size_t succeeded,
5662 std::size_t failed
5663 )
5664 {
5665 m_xml.scopedElement( "OverallResults" )
5666 .writeAttribute( "successes", succeeded )
5667 .writeAttribute( "failures", failed );
5668 m_xml.endElement();
5669 }
5670
5671 ///////////////////////////////////////////////////////////////////////////
5672 virtual void StartSection( const std::string& sectionName, const std::string description )
5673 {
5674 m_xml.startElement( "Section" )
5675 .writeAttribute( "name", sectionName )
5676 .writeAttribute( "description", description );
5677 }
5678
5679 ///////////////////////////////////////////////////////////////////////////
5680 virtual void EndSection( const std::string& /*sectionName*/, std::size_t succeeded, std::size_t failed )
5681 {
5682 m_xml.scopedElement( "OverallResults" )
5683 .writeAttribute( "successes", succeeded )
5684 .writeAttribute( "failures", failed );
5685 m_xml.endElement();
5686 }
5687
5688 ///////////////////////////////////////////////////////////////////////////
5689 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo )
5690 {
5691 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.getName() );
5692 m_currentTestSuccess = true;
5693 }
5694
5695 ///////////////////////////////////////////////////////////////////////////
5696 virtual void Result( const Catch::ResultInfo& resultInfo )
5697 {
5698 if( !m_config.includeSuccessfulResults() && resultInfo.getResultType() == ResultWas::Ok )
5699 return;
5700
5701 if( resultInfo.hasExpression() )
5702 {
5703 m_xml.startElement( "Expression" )
5704 .writeAttribute( "success", resultInfo.ok() )
5705 .writeAttribute( "filename", resultInfo.getFilename() )
5706 .writeAttribute( "line", resultInfo.getLine() );
5707
5708 m_xml.scopedElement( "Original" )
5709 .writeText( resultInfo.getExpression() );
5710 m_xml.scopedElement( "Expanded" )
5711 .writeText( resultInfo.getExpandedExpression() );
5712 m_currentTestSuccess &= resultInfo.ok();
5713 }
5714
5715 switch( resultInfo.getResultType() )
5716 {
5717 case ResultWas::ThrewException:
5718 m_xml.scopedElement( "Exception" )
5719 .writeAttribute( "filename", resultInfo.getFilename() )
5720 .writeAttribute( "line", resultInfo.getLine() )
5721 .writeText( resultInfo.getMessage() );
5722 m_currentTestSuccess = false;
5723 break;
5724 case ResultWas::Info:
5725 m_xml.scopedElement( "Info" )
5726 .writeText( resultInfo.getMessage() );
5727 break;
5728 case ResultWas::Warning:
5729 m_xml.scopedElement( "Warning" )
5730 .writeText( resultInfo.getMessage() );
5731 break;
5732 case ResultWas::ExplicitFailure:
5733 m_xml.scopedElement( "Failure" )
5734 .writeText( resultInfo.getMessage() );
5735 m_currentTestSuccess = false;
5736 break;
5737 default:
5738 break;
5739 }
5740 if( resultInfo.hasExpression() )
5741 m_xml.endElement();
5742 }
5743
5744 ///////////////////////////////////////////////////////////////////////////
5745 virtual void EndTestCase( const Catch::TestCaseInfo&, std::size_t /* succeeded */, std::size_t /* failed */, const std::string& /*stdOut*/, const std::string& /*stdErr*/ )
5746 {
5747 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
5748 m_xml.endElement();
5749 }
5750
5751 private:
5752 const IReporterConfig& m_config;
5753 bool m_currentTestSuccess;
5754 XmlWriter m_xml;
5755 };
5756
5757 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
5758
5759} // end namespace Catch
5760
5761// #included from: reporters/catch_reporter_junit.hpp
5762
5763/*
5764 * catch_reporter_junit.hpp
5765 * Catch
5766 *
5767 * Created by Phil on 26/11/2010.
5768 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
5769 *
5770 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5771 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5772 *
5773 */
5774#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
5775
5776
5777namespace Catch
5778{
5779 class JunitReporter : public Catch::IReporter
5780 {
5781 struct TestStats
5782 {
5783 std::string m_element;
5784 std::string m_resultType;
5785 std::string m_message;
5786 std::string m_content;
5787 };
5788
5789 struct TestCaseStats
5790 {
5791 TestCaseStats( const std::string& name = std::string() )
5792 : m_name( name )
5793 {
5794 }
5795
5796 double m_timeInSeconds;
5797 std::string m_status;
5798 std::string m_className;
5799 std::string m_name;
5800 std::vector<TestStats> m_testStats;
5801 };
5802
5803 struct Stats
5804 {
5805 Stats( const std::string& name = std::string() )
5806 : m_testsCount( 0 ),
5807 m_failuresCount( 0 ),
5808 m_disabledCount( 0 ),
5809 m_errorsCount( 0 ),
5810 m_timeInSeconds( 0 ),
5811 m_name( name )
5812 {
5813 }
5814
5815 std::size_t m_testsCount;
5816 std::size_t m_failuresCount;
5817 std::size_t m_disabledCount;
5818 std::size_t m_errorsCount;
5819 double m_timeInSeconds;
5820 std::string m_name;
5821
5822 std::vector<TestCaseStats> m_testCaseStats;
5823 };
5824
5825 public:
5826 ///////////////////////////////////////////////////////////////////////////
5827 JunitReporter( const IReporterConfig& config )
5828 : m_config( config ),
5829 m_testSuiteStats( "AllTests" ),
5830 m_currentStats( &m_testSuiteStats )
5831 {
5832 }
5833
5834 ///////////////////////////////////////////////////////////////////////////
5835 static std::string getDescription()
5836 {
5837 return "Reports test results in an XML format that looks like Ant's junitreport target";
5838 }
5839
5840 private: // IReporter
5841
5842 ///////////////////////////////////////////////////////////////////////////
5843 virtual void StartTesting()
5844 {
5845 }
5846
5847 ///////////////////////////////////////////////////////////////////////////
5848 virtual void StartGroup( const std::string& groupName )
5849 {
5850
5851 m_statsForSuites.push_back( Stats( groupName ) );
5852 m_currentStats = &m_statsForSuites.back();
5853 }
5854
5855 ///////////////////////////////////////////////////////////////////////////
5856 virtual void EndGroup( const std::string&, std::size_t succeeded, std::size_t failed )
5857 {
5858 m_currentStats->m_testsCount = failed+succeeded;
5859 m_currentStats = &m_testSuiteStats;
5860 }
5861
5862 virtual void StartSection( const std::string& /*sectionName*/, const std::string /*description*/ )
5863 {
5864 }
5865
5866 virtual void EndSection( const std::string& /*sectionName*/, std::size_t /*succeeded*/, std::size_t /*failed*/ )
5867 {
5868 }
5869
5870 ///////////////////////////////////////////////////////////////////////////
5871 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo )
5872 {
5873 m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getName() ) );
5874
5875 }
5876
5877 ///////////////////////////////////////////////////////////////////////////
5878 virtual void Result( const Catch::ResultInfo& resultInfo )
5879 {
5880 if( resultInfo.getResultType() != ResultWas::Ok || m_config.includeSuccessfulResults() )
5881 {
5882 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back();
5883 TestStats stats;
5884 std::ostringstream oss;
5885 if( !resultInfo.getMessage().empty() )
5886 {
5887 oss << resultInfo.getMessage() << " at ";
5888 }
5889 oss << resultInfo.getFilename() << ":" << resultInfo.getLine();
5890 stats.m_content = oss.str();
5891 stats.m_message = resultInfo.getExpandedExpression();
5892 stats.m_resultType = resultInfo.getTestMacroName();
5893 switch( resultInfo.getResultType() )
5894 {
5895 case ResultWas::ThrewException:
5896 stats.m_element = "error";
5897 m_currentStats->m_errorsCount++;
5898 break;
5899 case ResultWas::Info:
5900 stats.m_element = "info"; // !TBD ?
5901 break;
5902 case ResultWas::Warning:
5903 stats.m_element = "warning"; // !TBD ?
5904 break;
5905 case ResultWas::ExplicitFailure:
5906 stats.m_element = "failure";
5907 m_currentStats->m_failuresCount++;
5908 break;
5909 case ResultWas::ExpressionFailed:
5910 stats.m_element = "failure";
5911 m_currentStats->m_failuresCount++;
5912 break;
5913 case ResultWas::Ok:
5914 stats.m_element = "success";
5915 break;
5916 default:
5917 stats.m_element = "unknown";
5918 break;
5919 }
5920 testCaseStats.m_testStats.push_back( stats );
5921
5922 }
5923 }
5924
5925 ///////////////////////////////////////////////////////////////////////////
5926 virtual void EndTestCase( const Catch::TestCaseInfo&, std::size_t /* succeeded */, std::size_t /* failed */, const std::string& stdOut, const std::string& stdErr )
5927 {
5928 if( !stdOut.empty() )
5929 m_stdOut << stdOut << "\n";
5930 if( !stdErr.empty() )
5931 m_stdErr << stdErr << "\n";
5932 }
5933
5934 ///////////////////////////////////////////////////////////////////////////
5935 virtual void EndTesting( std::size_t /* succeeded */, std::size_t /* failed */ )
5936 {
5937 std::ostream& str = m_config.stream();
5938 {
5939 XmlWriter xml( str );
5940
5941 if( m_statsForSuites.size() > 0 )
5942 xml.startElement( "testsuites" );
5943
5944 std::vector<Stats>::const_iterator it = m_statsForSuites.begin();
5945 std::vector<Stats>::const_iterator itEnd = m_statsForSuites.end();
5946
5947 for(; it != itEnd; ++it )
5948 {
5949 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
5950 xml.writeAttribute( "name", it->m_name );
5951 xml.writeAttribute( "errors", it->m_errorsCount );
5952 xml.writeAttribute( "failures", it->m_failuresCount );
5953 xml.writeAttribute( "tests", it->m_testsCount );
5954 xml.writeAttribute( "hostname", "tbd" );
5955 xml.writeAttribute( "time", "tbd" );
5956 xml.writeAttribute( "timestamp", "tbd" );
5957
5958 OutputTestCases( xml, *it );
5959 }
5960
5961 xml.scopedElement( "system-out" ).writeText( trim( m_stdOut.str() ) );
5962 xml.scopedElement( "system-err" ).writeText( trim( m_stdOut.str() ) );
5963 }
5964 }
5965
5966 ///////////////////////////////////////////////////////////////////////////
5967 void OutputTestCases( XmlWriter& xml, const Stats& stats )
5968 {
5969 std::vector<TestCaseStats>::const_iterator it = stats.m_testCaseStats.begin();
5970 std::vector<TestCaseStats>::const_iterator itEnd = stats.m_testCaseStats.end();
5971 for(; it != itEnd; ++it )
5972 {
5973 xml.writeBlankLine();
5974 xml.writeComment( "Test case" );
5975
5976 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
5977 xml.writeAttribute( "classname", it->m_className );
5978 xml.writeAttribute( "name", it->m_name );
5979 xml.writeAttribute( "time", "tbd" );
5980
5981 OutputTestResult( xml, *it );
5982 }
5983 }
5984
5985
5986 ///////////////////////////////////////////////////////////////////////////
5987 void OutputTestResult( XmlWriter& xml, const TestCaseStats& stats )
5988 {
5989 std::vector<TestStats>::const_iterator it = stats.m_testStats.begin();
5990 std::vector<TestStats>::const_iterator itEnd = stats.m_testStats.end();
5991 for(; it != itEnd; ++it )
5992 {
5993 if( it->m_element != "success" )
5994 {
5995 XmlWriter::ScopedElement e = xml.scopedElement( it->m_element );
5996
5997 xml.writeAttribute( "message", it->m_message );
5998 xml.writeAttribute( "type", it->m_resultType );
5999 if( !it->m_content.empty() )
6000 xml.writeText( it->m_content );
6001 }
6002 }
6003 }
6004
6005 private:
6006 const IReporterConfig& m_config;
6007 bool m_currentTestSuccess;
6008
6009 Stats m_testSuiteStats;
6010 Stats* m_currentStats;
6011 std::vector<Stats> m_statsForSuites;
6012 std::ostringstream m_stdOut;
6013 std::ostringstream m_stdErr;
6014 };
6015
6016 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
6017
6018} // end namespace Catch
6019
6020
6021#include <fstream>
6022#include <stdlib.h>
6023#include <limits>
6024
6025namespace Catch
6026{
6027 //////////////////////////////////////////////////////////////////////////
6028 inline int Main
6029 (
6030 Config& config
6031 )
6032 {
6033 // Handle list request
6034 if( config.listWhat() != Config::List::None )
6035 return List( config );
6036
6037 // Open output file, if specified
6038 std::ofstream ofs;
6039 if( !config.getFilename().empty() )
6040 {
6041 ofs.open( config.getFilename().c_str() );
6042 if( ofs.fail() )
6043 {
6044 std::cerr << "Unable to open file: '" << config.getFilename() << "'" << std::endl;
6045 return (std::numeric_limits<int>::max)();
6046 }
6047 config.setStreamBuf( ofs.rdbuf() );
6048 }
6049
6050 Runner runner( config );
6051
6052 // Run test specs specified on the command line - or default to all
6053 if( !config.testsSpecified() )
6054 {
6055 config.getReporter()->StartGroup( "" );
6056 runner.runAll();
6057 config.getReporter()->EndGroup( "", runner.getSuccessCount(), runner.getFailureCount() );
6058 }
6059 else
6060 {
6061 // !TBD We should get all the testcases upfront, report any missing,
6062 // then just run them
6063 std::vector<std::string>::const_iterator it = config.getTestSpecs().begin();
6064 std::vector<std::string>::const_iterator itEnd = config.getTestSpecs().end();
6065 for(; it != itEnd; ++it )
6066 {
6067 size_t prevSuccess = runner.getSuccessCount();
6068 size_t prevFail = runner.getFailureCount();
6069 config.getReporter()->StartGroup( *it );
6070 if( runner.runMatching( *it ) == 0 )
6071 {
6072 // Use reporter?
6073// std::cerr << "\n[Unable to match any test cases with: " << *it << "]" << std::endl;
6074 }
6075 config.getReporter()->EndGroup( *it, runner.getSuccessCount()-prevSuccess, runner.getFailureCount()-prevFail );
6076 }
6077 }
6078 return static_cast<int>( runner.getFailureCount() );
6079 }
6080
6081 //////////////////////////////////////////////////////////////////////////
6082 void showHelp
6083 (
6084 std::string exeName
6085 )
6086 {
6087 std::string::size_type pos = exeName.find_last_of( "/\\" );
6088 if( pos != std::string::npos )
6089 {
6090 exeName = exeName.substr( pos+1 );
6091 }
6092
6093 std::cout << exeName << " is a CATCH host application. Options are as follows:\n\n"
6094 << "\t-l, --list <tests | reporters> [xml]\n"
6095 << "\t-t, --test <testspec> [<testspec>...]\n"
6096 << "\t-r, --reporter <reporter name>\n"
6097 << "\t-o, --out <file name>|<%stream name>\n"
6098 << "\t-s, --success\n"
6099 << "\t-b, --break\n"
6100 << "\t-n, --name <name>\n\n"
6101 << "For more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line" << std::endl;
6102 }
6103
6104 //////////////////////////////////////////////////////////////////////////
6105 inline int Main
6106 (
6107 int argc,
6108 char* const argv[],
6109 Config& config
6110 )
6111 {
6112 ArgParser( argc, argv, config );
6113
6114 if( !config.getMessage().empty() )
6115 {
6116 std::cerr << config.getMessage() << std::endl;
6117 return (std::numeric_limits<int>::max)();
6118 }
6119
6120 // Handle help
6121 if( config.showHelp() )
6122 {
6123 showHelp( argv[0] );
6124 return 0;
6125 }
6126
6127 return Main( config );
6128 }
6129
6130 //////////////////////////////////////////////////////////////////////////
6131 inline int Main
6132 (
6133 int argc,
6134 char* const argv[]
6135 )
6136 {
6137 Config config;
6138// if( isDebuggerActive() )
6139// config.useStream( "debug" );
6140 return Main( argc, argv, config );
6141 }
6142
6143} // end namespace Catch
6144
6145#endif
6146
6147#ifdef CATCH_CONFIG_MAIN
6148// #included from: internal/catch_default_main.hpp
6149
6150/*
6151 * catch_default_main.hpp
6152 * Catch
6153 *
6154 * Created by Phil on 20/05/2011.
6155 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
6156 *
6157 * Distributed under the Boost Software License, Version 1.0. (See accompanying
6158 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6159 *
6160 */
6161
6162#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
6163
6164int main (int argc, char * const argv[])
6165{
6166#ifdef __OBJC__
6167
6168 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
6169
6170 Catch::registerTestMethods();
6171
6172 int result = Catch::Main( argc, (char* const*)argv );
6173
6174 [pool drain];
6175 return result;
6176
6177#else
6178
6179 return Catch::Main( argc, argv );
6180
6181#endif
6182}
6183
6184
6185#endif
6186
Phil Nash89d1e6c2011-05-24 08:23:02 +01006187//////
6188
6189#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "REQUIRE" )
6190#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "REQUIRE_FALSE" )
6191
6192#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "REQUIRE_THROWS" )
6193#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "REQUIRE_THROWS_AS" )
6194#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "REQUIRE_NOTHROW" )
6195
6196#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CHECK" )
6197#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CHECK_FALSE" )
6198
6199#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CHECK_THROWS" )
6200#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" )
6201#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CHECK_NOTHROW" )
6202
6203#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" )
6204#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" )
6205#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
6206#define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
6207#define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CAPTURE" )
6208
6209#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
6210
6211#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
6212#define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
6213#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
6214#define METHOD_AS_TEST_CASE( method, name, description ) CATCH_METHOD_AS_TEST_CASE( method, name, description )
6215
6216#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
6217#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
6218
6219#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
6220
6221///////////////
6222// Still to be implemented
6223#define CHECK_NOFAIL( expr ) // !TBD - reports violation, but doesn't fail Test
6224
6225using Catch::Detail::Approx;
6226
6227#endif // TWOBLUECUBES_CATCH_HPP_INCLUDED
6228