blob: b3c17a62f599b3745940cc7e81962287c6f7278f [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
971#elif defined(CATCH_PLATFORM_WINDOWS)
972 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
1511};
1512
1513template<typename T>
1514class Expression
1515{
1516 void operator = ( const Expression& );
1517
1518public:
1519 ///////////////////////////////////////////////////////////////////////////
1520 Expression
1521 (
1522 MutableResultInfo& result,
1523 const T& lhs
1524 )
1525 : m_result( result ),
1526 m_lhs( lhs )
1527 {
1528 }
1529
1530 ///////////////////////////////////////////////////////////////////////////
1531 template<typename RhsT>
1532 MutableResultInfo& operator ==
1533 (
1534 const RhsT& rhs
1535 )
1536 {
1537 return m_result.captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1538 }
1539
1540 ///////////////////////////////////////////////////////////////////////////
1541 template<typename RhsT>
1542 MutableResultInfo& operator !=
1543 (
1544 const RhsT& rhs
1545 )
1546 {
1547 return m_result.captureExpression<Internal::IsNotEqualTo>( 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::IsLessThan>( 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::IsGreaterThan>( 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::IsLessThanOrEqualTo>( 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::IsGreaterThanOrEqualTo>( m_lhs, rhs );
1588 }
1589
1590 ///////////////////////////////////////////////////////////////////////////
1591 operator MutableResultInfo&
1592 ()
1593 {
1594 return m_result.captureBoolExpression( m_lhs );
1595 }
1596
1597 ///////////////////////////////////////////////////////////////////////////
1598 template<typename RhsT>
1599 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator +
1600 (
1601 const RhsT&
1602 );
1603
1604 ///////////////////////////////////////////////////////////////////////////
1605 template<typename RhsT>
1606 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator -
1607 (
1608 const RhsT&
1609 );
1610
1611private:
1612 MutableResultInfo& m_result;
1613 const T& m_lhs;
1614};
1615
1616template<typename LhsT>
1617class PtrExpression
1618{
1619public:
1620
1621 ///////////////////////////////////////////////////////////////////////////
1622 PtrExpression
1623 (
1624 MutableResultInfo& result,
1625 const LhsT* lhs
1626 )
1627 : m_result( &result ),
1628 m_lhs( lhs )
1629 {}
1630
1631 ///////////////////////////////////////////////////////////////////////////
1632 template<typename RhsT>
1633 MutableResultInfo& operator ==
1634 (
1635 const RhsT* rhs
1636 )
1637 {
1638 return m_result->captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1639 }
1640
1641 ///////////////////////////////////////////////////////////////////////////
1642 // This catches NULL
1643 MutableResultInfo& operator ==
1644 (
1645 LhsT* rhs
1646 )
1647 {
1648 return m_result->captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
1649 }
1650
1651 ///////////////////////////////////////////////////////////////////////////
1652 template<typename RhsT>
1653 MutableResultInfo& operator !=
1654 (
1655 const RhsT* rhs
1656 )
1657 {
1658 return m_result->captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1659 }
1660
1661 ///////////////////////////////////////////////////////////////////////////
1662 // This catches NULL
1663 MutableResultInfo& operator !=
1664 (
1665 LhsT* rhs
1666 )
1667 {
1668 return m_result->captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
1669 }
1670
1671 ///////////////////////////////////////////////////////////////////////////
1672 operator MutableResultInfo&
1673 ()
1674 {
1675 return m_result->captureBoolExpression( m_lhs );
1676 }
1677
1678
1679private:
1680 MutableResultInfo* m_result;
1681 const LhsT* m_lhs;
1682};
1683
1684class ResultBuilder
1685{
1686public:
1687
1688 ///////////////////////////////////////////////////////////////////////////
1689 ResultBuilder
1690 (
1691 const char* filename,
1692 std::size_t line,
1693 const char* macroName,
1694 const char* expr = "",
1695 bool isNot = false
1696 )
1697 : m_result( expr, isNot, filename, line, macroName )
1698 {}
1699
1700 ///////////////////////////////////////////////////////////////////////////
1701 template<typename T>
1702 Expression<T> operator->*
1703 (
1704 const T & operand
1705 )
1706 {
1707 Expression<T> expr( m_result, operand );
1708
1709 return expr;
1710 }
1711
1712 ///////////////////////////////////////////////////////////////////////////
Phil Nash62a5ddc2011-06-29 19:25:14 +01001713 Expression<const char*> operator->*
1714 (
1715 const char* operand
1716 )
1717 {
1718 Expression<const char*> expr( m_result, operand );
1719
1720 return expr;
1721 }
1722
1723 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01001724 template<typename T>
1725 PtrExpression<T> operator->*
1726 (
1727 const T* operand
1728 )
1729 {
1730 PtrExpression<T> expr( m_result, operand );
1731
1732 return expr;
1733 }
1734
1735 ///////////////////////////////////////////////////////////////////////////
1736 template<typename T>
1737 PtrExpression<T> operator->*
1738 (
1739 T* operand
1740 )
1741 {
1742 PtrExpression<T> expr( m_result, operand );
1743
1744 return expr;
1745 }
1746
1747 ///////////////////////////////////////////////////////////////////////////
1748 template<typename T>
1749 ResultBuilder& operator <<
1750 (
1751 const T & value
1752 )
1753 {
1754 m_messageStream << Catch::toString( value );
1755 return *this;
1756 }
1757
1758 ///////////////////////////////////////////////////////////////////////////
1759 ResultBuilder& setResultType
1760 (
1761 ResultWas::OfType resultType
1762 )
1763 {
1764 m_result.setResultType( resultType );
1765 return *this;
1766 }
1767
1768 ///////////////////////////////////////////////////////////////////////////
1769 operator MutableResultInfo&
1770 ()
1771 {
1772 m_result.setMessage( m_messageStream.str() );
1773 return m_result;
1774 }
1775
1776private:
1777 MutableResultInfo m_result;
1778 std::ostringstream m_messageStream;
1779
1780};
1781
1782class ScopedInfo
1783{
1784public:
1785 ///////////////////////////////////////////////////////////////////////////
1786 ScopedInfo
1787 ()
1788 {
1789 Hub::getResultCapture().pushScopedInfo( this );
1790 }
1791
1792 ///////////////////////////////////////////////////////////////////////////
1793 ~ScopedInfo
1794 ()
1795 {
1796 Hub::getResultCapture().popScopedInfo( this );
1797 }
1798
1799 ///////////////////////////////////////////////////////////////////////////
1800 ScopedInfo& operator <<
1801 (
1802 const char* str
1803 )
1804 {
1805 m_oss << str;
1806 return *this;
1807 }
1808
1809 ///////////////////////////////////////////////////////////////////////////
1810 std::string getInfo
1811 ()
1812 const
1813 {
1814 return m_oss.str();
1815 }
1816
1817private:
1818 std::ostringstream m_oss;
1819};
1820
1821///////////////////////////////////////////////////////////////////////////////
1822// This is just here to avoid compiler warnings with macro constants
1823inline bool isTrue
1824(
1825 bool value
1826)
1827{
1828 return value;
1829}
1830
1831} // end namespace Catch
1832
1833///////////////////////////////////////////////////////////////////////////////
1834#define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure ) \
Phil Nash3c20a752011-06-23 08:23:33 +01001835 if( Catch::ResultAction::Value internal_catch_action = Catch::Hub::getResultCapture().acceptExpression( expr ) ) \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001836 { \
Phil Nash3c20a752011-06-23 08:23:33 +01001837 if( internal_catch_action == Catch::ResultAction::DebugFailed ) BreakIntoDebugger(); \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001838 if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \
1839 }
1840
1841///////////////////////////////////////////////////////////////////////////////
1842#define INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ) \
1843 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr, isNot )->*expr ), stopOnFailure ); \
Phil Nash3c20a752011-06-23 08:23:33 +01001844 if( Catch::isTrue( false ) ){ bool internal_catch_dummyResult = ( expr ); Catch::isTrue( internal_catch_dummyResult ); }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001845
1846///////////////////////////////////////////////////////////////////////////////
1847#define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \
1848 try \
1849 { \
1850 expr; \
1851 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure ); \
1852 } \
Phil Nash3c20a752011-06-23 08:23:33 +01001853 catch( std::exception& internal_catch_exception ) \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001854 { \
Phil Nash3c20a752011-06-23 08:23:33 +01001855 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 +01001856 } \
1857 catch( ... ) \
1858 { \
1859 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \
1860 }
1861
1862///////////////////////////////////////////////////////////////////////////////
1863#define INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
1864 try \
1865 { \
1866 expr; \
1867 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure ); \
1868 } \
1869 catch( Catch::TestFailureException& ) \
1870 { \
1871 throw; \
1872 } \
1873 catch( exceptionType ) \
1874 { \
1875 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure ); \
1876 }
1877
1878///////////////////////////////////////////////////////////////////////////////
1879#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, stopOnFailure, macroName ) \
1880 INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
1881 catch( ... ) \
1882 { \
1883 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \
1884 }
1885
1886///////////////////////////////////////////////////////////////////////////////
1887#define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \
1888 Catch::Hub::getResultCapture().acceptExpression( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName ) << reason ).setResultType( resultType ) );
1889
1890///////////////////////////////////////////////////////////////////////////////
1891#define INTERNAL_CATCH_SCOPED_INFO( log ) \
1892 Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
1893 INTERNAL_CATCH_UNIQUE_NAME( info ) << log
1894
1895// #included from: internal/catch_section.hpp
1896
1897/*
1898 * catch_section.hpp
1899 * Catch
1900 *
1901 * Created by Phil on 03/11/2010.
1902 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
1903 *
1904 * Distributed under the Boost Software License, Version 1.0. (See accompanying
1905 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1906 *
1907 */
1908
1909#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
1910
1911
1912#include <string>
1913
1914namespace Catch
1915{
1916 class Section
1917 {
1918 public:
1919 ///////////////////////////////////////////////////////////////////////
1920 Section
1921 (
1922 const std::string& name,
1923 const std::string& description,
1924 const std::string& filename,
1925 std::size_t line
1926 )
1927 : m_name( name ),
1928 m_sectionIncluded( Hub::getResultCapture().sectionStarted( name, description, filename, line, m_successes, m_failures ) )
1929 {
1930 }
1931
1932 ///////////////////////////////////////////////////////////////////////
1933 ~Section
1934 ()
1935 {
1936 if( m_sectionIncluded )
1937 Hub::getResultCapture().sectionEnded( m_name, m_successes, m_failures );
1938 }
1939
1940 ///////////////////////////////////////////////////////////////////////
1941 // This indicates whether the section should be executed or not
1942 operator bool
1943 ()
1944 {
1945 return m_sectionIncluded;
1946 }
1947
1948 private:
1949
1950 std::string m_name;
1951 std::size_t m_successes;
1952 std::size_t m_failures;
1953 bool m_sectionIncluded;
1954 };
1955
1956} // end namespace Catch
1957
1958#define INTERNAL_CATCH_SECTION( name, desc ) \
1959 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, __FILE__, __LINE__ ) )
1960
1961// #included from: internal/catch_generators.hpp
1962
1963/*
1964 * catch_generators.hpp
1965 * Catch
1966 *
1967 * Created by Phil on 27/01/2011.
1968 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
1969 *
1970 * Distributed under the Boost Software License, Version 1.0. (See accompanying
1971 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1972 *
1973 */
1974
1975#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
1976
1977
1978#include <iterator>
1979#include <vector>
1980#include <string>
1981#include <stdlib.h>
1982
1983namespace Catch
1984{
1985
1986template<typename T>
1987struct IGenerator
1988{
1989 virtual ~IGenerator
1990 ()
1991 {}
1992
1993 virtual T getValue
1994 ( std::size_t index
1995 ) const = 0;
1996
1997 virtual std::size_t size
1998 () const = 0;
1999};
2000
2001template<typename T>
2002class BetweenGenerator : public IGenerator<T>
2003{
2004public:
2005 ///////////////////////////////////////////////////////////////////////////
2006 BetweenGenerator
2007 (
2008 T from,
2009 T to
2010 )
2011 : m_from( from ),
2012 m_to( to )
2013 {
2014 }
2015
2016 ///////////////////////////////////////////////////////////////////////////
2017 virtual T getValue
2018 (
2019 std::size_t index
2020 )
2021 const
2022 {
2023 return m_from+static_cast<T>( index );
2024 }
2025
2026 ///////////////////////////////////////////////////////////////////////////
2027 virtual std::size_t size
2028 ()
2029 const
2030 {
2031 return 1+m_to-m_from;
2032 }
2033
2034private:
2035
2036 T m_from;
2037 T m_to;
2038};
2039
2040template<typename T>
2041class ValuesGenerator : public IGenerator<T>
2042{
2043public:
2044 ///////////////////////////////////////////////////////////////////////////
2045 ValuesGenerator
2046 ()
2047 {
2048 }
2049
2050 ///////////////////////////////////////////////////////////////////////////
2051 void add
2052 (
2053 T value
2054 )
2055 {
2056 m_values.push_back( value );
2057 }
2058
2059 ///////////////////////////////////////////////////////////////////////////
2060 virtual T getValue
2061 (
2062 std::size_t index
2063 )
2064 const
2065 {
2066 return m_values[index];
2067 }
2068
2069 ///////////////////////////////////////////////////////////////////////////
2070 virtual std::size_t size
2071 ()
2072 const
2073 {
2074 return m_values.size();
2075 }
2076
2077private:
2078
2079 std::vector<T> m_values;
2080};
2081
2082template<typename T>
2083class CompositeGenerator
2084{
2085public:
2086 ///////////////////////////////////////////////////////////////////////////
2087 CompositeGenerator()
2088 : m_totalSize( 0 )
2089 {
2090 }
2091
2092 ///////////////////////////////////////////////////////////////////////////
2093 // *** Move semantics, similar to auto_ptr ***
2094 CompositeGenerator( CompositeGenerator& other )
2095 : m_fileInfo( other.m_fileInfo ),
2096 m_totalSize( 0 )
2097 {
2098 move( other );
2099 }
2100
2101 ///////////////////////////////////////////////////////////////////////////
2102 CompositeGenerator& setFileInfo
2103 (
2104 const char* fileInfo
2105 )
2106 {
2107 m_fileInfo = fileInfo;
2108 return *this;
2109 }
2110
2111 ///////////////////////////////////////////////////////////////////////////
2112 ~CompositeGenerator
2113 ()
2114 {
2115 deleteAll( m_composed );
2116 }
2117
2118 ///////////////////////////////////////////////////////////////////////////
2119 operator T
2120 ()
2121 const
2122 {
2123 size_t overallIndex = Hub::getGeneratorIndex( m_fileInfo, m_totalSize );
2124
2125 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2126 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2127 for( size_t index = 0; it != itEnd; ++it )
2128 {
2129 const IGenerator<T>* generator = *it;
2130 if( overallIndex >= index && overallIndex < index + generator->size() )
2131 {
2132 return generator->getValue( overallIndex-index );
2133 }
2134 index += generator->size();
2135 }
2136 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
2137 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
2138 }
2139
2140 ///////////////////////////////////////////////////////////////////////////
2141 void add
2142 (
2143 const IGenerator<T>* generator
2144 )
2145 {
2146 m_totalSize += generator->size();
2147 m_composed.push_back( generator );
2148 }
2149
2150 ///////////////////////////////////////////////////////////////////////////
2151 CompositeGenerator& then
2152 (
2153 CompositeGenerator& other
2154 )
2155 {
2156 move( other );
2157 return *this;
2158 }
2159
2160 ///////////////////////////////////////////////////////////////////////////
2161 CompositeGenerator& then
2162 (
2163 T value
2164 )
2165 {
2166 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2167 valuesGen->add( value );
2168 add( valuesGen );
2169 return *this;
2170 }
2171
2172private:
2173
2174 ///////////////////////////////////////////////////////////////////////////
2175 void move
2176 (
2177 CompositeGenerator& other
2178 )
2179 {
2180 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
2181 m_totalSize += other.m_totalSize;
2182 other.m_composed.clear();
2183 }
2184
2185 std::vector<const IGenerator<T>*> m_composed;
2186 std::string m_fileInfo;
2187 size_t m_totalSize;
2188};
2189
2190namespace Generators
2191{
2192 ///////////////////////////////////////////////////////////////////////////
2193 template<typename T>
2194 CompositeGenerator<T> between
2195 (
2196 T from,
2197 T to
2198 )
2199 {
2200 CompositeGenerator<T> generators;
2201 generators.add( new BetweenGenerator<T>( from, to ) );
2202 return generators;
2203 }
2204
2205 ///////////////////////////////////////////////////////////////////////////
2206 template<typename T>
2207 CompositeGenerator<T> values
2208 (
2209 T val1,
2210 T val2
2211 )
2212 {
2213 CompositeGenerator<T> generators;
2214 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2215 valuesGen->add( val1 );
2216 valuesGen->add( val2 );
2217 generators.add( valuesGen );
2218 return generators;
2219 }
2220
2221 ///////////////////////////////////////////////////////////////////////////
2222 template<typename T>
2223 CompositeGenerator<T> values
2224 (
2225 T val1,
2226 T val2,
2227 T val3
2228 )
2229 {
2230 CompositeGenerator<T> generators;
2231 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2232 valuesGen->add( val1 );
2233 valuesGen->add( val2 );
2234 valuesGen->add( val3 );
2235 generators.add( valuesGen );
2236 return generators;
2237 }
2238
2239 ///////////////////////////////////////////////////////////////////////////
2240 template<typename T>
2241 CompositeGenerator<T> values
2242 (
2243 T val1,
2244 T val2,
2245 T val3,
2246 T val4
2247 )
2248 {
2249 CompositeGenerator<T> generators;
2250 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2251 valuesGen->add( val1 );
2252 valuesGen->add( val2 );
2253 valuesGen->add( val3 );
2254 valuesGen->add( val4 );
2255 generators.add( valuesGen );
2256 return generators;
2257 }
2258
2259} // end namespace Generators
2260
2261using namespace Generators;
2262
2263} // end namespace Catch
2264
2265#define INTERNAL_CATCH_LINESTR2( line ) #line
2266#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2267
2268#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2269
2270// #included from: internal/catch_interfaces_exception.h
2271
2272/*
2273 * catch_exception_interfaces.h
2274 * Catch
2275 *
2276 * Created by Phil on 20/04/2011.
2277 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
2278 *
2279 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2280 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2281 *
2282 */
2283#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTIONS_H_INCLUDED
2284
2285#include <string>
2286
2287namespace Catch
2288{
2289 typedef std::string(*exceptionTranslateFunction)();
2290
2291 struct IExceptionTranslator
2292 {
2293 virtual ~IExceptionTranslator(){}
2294 virtual std::string translate() const = 0;
2295 };
2296
2297 struct IExceptionTranslatorRegistry
2298 {
2299 virtual ~IExceptionTranslatorRegistry
2300 ()
2301 {}
2302
2303 virtual void registerTranslator
2304 ( IExceptionTranslator* translator
2305 ) = 0;
2306 virtual std::string translateActiveException
2307 () const = 0;
2308
2309 };
2310
2311 class ExceptionTranslatorRegistrar
2312 {
2313 template<typename T>
2314 class ExceptionTranslator : public IExceptionTranslator
2315 {
2316 public:
2317
2318 ExceptionTranslator
2319 (
2320 std::string(*translateFunction)( T& )
2321 )
2322 : m_translateFunction( translateFunction )
2323 {}
2324
2325 virtual std::string translate
2326 ()
2327 const
2328 {
2329 try
2330 {
2331 throw;
2332 }
2333 catch( T& ex )
2334 {
2335 return m_translateFunction( ex );
2336 }
2337 }
2338
2339 protected:
2340 std::string(*m_translateFunction)( T& );
2341 };
2342
2343 public:
2344 template<typename T>
2345 ExceptionTranslatorRegistrar
2346 (
2347 std::string(*translateFunction)( T& )
2348 )
2349 {
2350 Catch::Hub::getExceptionTranslatorRegistry().registerTranslator
2351 ( new ExceptionTranslator<T>( translateFunction ) );
2352 }
2353 };
2354}
2355
2356///////////////////////////////////////////////////////////////////////////////
2357#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2358 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2359 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2360 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2361
2362// #included from: internal/catch_approx.hpp
2363
2364/*
2365 * catch_approx.hpp
2366 * Catch
2367 *
2368 * Created by Phil on 28/04/2011.
2369 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2370 *
2371 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2372 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2373 *
2374 */
2375#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2376
2377
2378#include <cmath>
2379#include <limits>
2380
2381namespace Catch
2382{
2383 namespace Detail
2384 {
2385 class Approx
2386 {
2387 public:
2388 ///////////////////////////////////////////////////////////////////////////
2389 explicit Approx
2390 (
Phil Nashf721a962011-06-07 14:13:57 +01002391 double value
Phil Nash89d1e6c2011-05-24 08:23:02 +01002392 )
Phil Nashf721a962011-06-07 14:13:57 +01002393 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
Phil Nash89d1e6c2011-05-24 08:23:02 +01002394 m_scale( 1.0 ),
Phil Nashf721a962011-06-07 14:13:57 +01002395 m_value( value )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002396 {
2397 }
2398
2399 ///////////////////////////////////////////////////////////////////////////
Phil Nashf721a962011-06-07 14:13:57 +01002400 Approx
2401 (
2402 const Approx& other
2403 )
2404 : m_epsilon( other.m_epsilon ),
2405 m_scale( other.m_scale ),
2406 m_value( other.m_value )
2407 {
2408 }
2409
2410 ///////////////////////////////////////////////////////////////////////////
2411 static Approx custom
2412 ()
2413 {
2414 return Approx( 0 );
2415 }
2416
2417 ///////////////////////////////////////////////////////////////////////////
2418 Approx operator()
2419 (
2420 double value
2421 )
2422 {
2423 Approx approx( value );
2424 approx.epsilon( m_epsilon );
2425 approx.scale( m_scale );
2426 return approx;
2427 }
2428
2429 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002430 friend bool operator ==
2431 (
Phil Nash6b6143c2011-05-31 07:51:04 +01002432 double lhs,
Phil Nash89d1e6c2011-05-24 08:23:02 +01002433 const Approx& rhs
2434 )
2435 {
2436 // Thanks to Richard Harris for his help refining this formula
Phil Nashf721a962011-06-07 14:13:57 +01002437 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 +01002438 }
2439
2440 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002441 friend bool operator ==
2442 (
2443 const Approx& lhs,
Phil Nash6b6143c2011-05-31 07:51:04 +01002444 double rhs
Phil Nash89d1e6c2011-05-24 08:23:02 +01002445 )
2446 {
2447 return operator==( rhs, lhs );
2448 }
2449
2450 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002451 friend bool operator !=
2452 (
Phil Nash6b6143c2011-05-31 07:51:04 +01002453 double lhs,
Phil Nash89d1e6c2011-05-24 08:23:02 +01002454 const Approx& rhs
2455 )
2456 {
2457 return !operator==( lhs, rhs );
2458 }
2459
2460 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002461 friend bool operator !=
2462 (
2463 const Approx& lhs,
Phil Nash6b6143c2011-05-31 07:51:04 +01002464 double rhs
Phil Nash89d1e6c2011-05-24 08:23:02 +01002465 )
2466 {
2467 return !operator==( rhs, lhs );
2468 }
2469
2470
2471 ///////////////////////////////////////////////////////////////////////////
2472 Approx& epsilon
2473 (
2474 double newEpsilon
2475 )
2476 {
2477 m_epsilon = newEpsilon;
2478 return *this;
2479 }
2480
2481 ///////////////////////////////////////////////////////////////////////////
2482 Approx& scale
2483 (
2484 double newScale
2485 )
2486 {
2487 m_scale = newScale;
2488 return *this;
2489 }
2490
2491 ///////////////////////////////////////////////////////////////////////////
2492 std::string toString() const
2493 {
2494 std::ostringstream oss;
Phil Nashf721a962011-06-07 14:13:57 +01002495 oss << "Approx( " << m_value << ")";
Phil Nash89d1e6c2011-05-24 08:23:02 +01002496 return oss.str();
2497 }
2498
2499 private:
2500 double m_epsilon;
2501 double m_scale;
Phil Nashf721a962011-06-07 14:13:57 +01002502 double m_value;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002503 };
2504 }
2505
2506 ///////////////////////////////////////////////////////////////////////////////
2507 template<>
2508 inline std::string toString<Detail::Approx>
2509 (
2510 const Detail::Approx& value
2511 )
2512 {
2513 return value.toString();
2514 }
2515
2516} // end namespace Catch
2517
2518
2519#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
2520// #included from: catch_runner.hpp
2521
2522/*
2523 * catch_runner.hpp
2524 * Catch
2525 *
2526 * Created by Phil on 31/10/2010.
2527 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2528 *
2529 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2530 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2531 *
2532 */
2533
2534#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
2535
2536// #included from: internal/catch_hub_impl.hpp
2537
2538/*
2539 * catch_hub_impl.hpp
2540 * Catch
2541 *
2542 * Created by Phil on 31/12/2010.
2543 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2544 *
2545 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2546 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2547 *
2548 */
2549// #included from: catch_reporter_registry.hpp
2550
2551/*
2552 * catch_reporter_registry.hpp
2553 * Catch
2554 *
2555 * Created by Phil on 29/10/2010.
2556 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2557 *
2558 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2559 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2560 *
2561 */
2562#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
2563
2564
2565#include <map>
2566
2567namespace Catch
2568{
2569 class ReporterRegistry : public IReporterRegistry
2570 {
2571 public:
2572
2573 ///////////////////////////////////////////////////////////////////////
2574 ~ReporterRegistry
2575 ()
2576 {
2577 deleteAllValues( m_factories );
2578 }
2579
2580 ///////////////////////////////////////////////////////////////////////
2581 virtual IReporter* create
2582 (
2583 const std::string& name,
2584 const IReporterConfig& config
2585 )
2586 const
2587 {
2588 FactoryMap::const_iterator it = m_factories.find( name );
2589 if( it == m_factories.end() )
2590 return NULL;
2591 return it->second->create( config );
2592 }
2593
2594 ///////////////////////////////////////////////////////////////////////
2595 void registerReporter
2596 (
2597 const std::string& name,
2598 IReporterFactory* factory
2599 )
2600 {
2601 m_factories.insert( std::make_pair( name, factory ) );
2602 }
2603
2604 ///////////////////////////////////////////////////////////////////////
2605 const FactoryMap& getFactories
2606 ()
2607 const
2608 {
2609 return m_factories;
2610 }
2611
2612 private:
2613 FactoryMap m_factories;
2614 };
2615}
2616
2617// #included from: catch_test_case_registry_impl.hpp
2618
2619/*
2620 * catch_test_case_registry_impl.hpp
2621 * Catch
2622 *
2623 * Created by Phil on 7/1/2011
2624 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2625 *
2626 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2627 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2628 *
2629 */
2630
2631// #included from: catch_test_case_info.hpp
2632
2633/*
2634 * catch_test_case_info.hpp
2635 * Catch
2636 *
2637 * Created by Phil on 29/10/2010.
2638 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2639 *
2640 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2641 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2642 *
2643 */
2644
2645#define TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED
2646
2647#include <map>
2648#include <string>
2649
2650namespace Catch
2651{
2652 class TestCaseInfo
2653 {
2654 public:
2655 ///////////////////////////////////////////////////////////////////////
2656 TestCaseInfo
2657 (
2658 ITestCase* testCase,
2659 const char* name,
2660 const char* description,
2661 const char* filename,
2662 std::size_t line
2663 )
2664 : m_test( testCase ),
2665 m_name( name ),
2666 m_description( description ),
2667 m_filename( filename ),
2668 m_line( line )
2669 {
2670 }
2671
2672 ///////////////////////////////////////////////////////////////////////
2673 TestCaseInfo
2674 ()
2675 : m_test( NULL )
2676 {
2677 }
2678
2679 ///////////////////////////////////////////////////////////////////////
2680 TestCaseInfo
2681 (
2682 const TestCaseInfo& other
2683 )
2684 : m_test( other.m_test->clone() ),
2685 m_name( other.m_name ),
2686 m_description( other.m_description ),
2687 m_filename( other.m_filename ),
2688 m_line( other.m_line )
2689 {
2690 }
2691
2692 ///////////////////////////////////////////////////////////////////////
2693 TestCaseInfo
2694 (
2695 const TestCaseInfo& other,
2696 const std::string& name
2697 )
2698 : m_test( other.m_test->clone() ),
2699 m_name( name ),
2700 m_description( other.m_description ),
2701 m_filename( other.m_filename ),
2702 m_line( other.m_line )
2703 {
2704 }
2705
2706 ///////////////////////////////////////////////////////////////////////
2707 TestCaseInfo& operator =
2708 (
2709 const TestCaseInfo& other
2710 )
2711 {
2712 TestCaseInfo temp( other );
2713 swap( temp );
2714 return *this;
2715 }
2716
2717 ///////////////////////////////////////////////////////////////////////
2718 ~TestCaseInfo
2719 ()
2720 {
2721 delete m_test;
2722 }
2723
2724 ///////////////////////////////////////////////////////////////////////
2725 void invoke
2726 ()
2727 const
2728 {
2729 m_test->invoke();
2730 }
2731
2732 ///////////////////////////////////////////////////////////////////////
2733 const std::string& getName
2734 ()
2735 const
2736 {
2737 return m_name;
2738 }
2739
2740 ///////////////////////////////////////////////////////////////////////
2741 const std::string& getDescription
2742 ()
2743 const
2744 {
2745 return m_description;
2746 }
2747
2748 ///////////////////////////////////////////////////////////////////////
2749 const std::string& getFilename
2750 ()
2751 const
2752 {
2753 return m_filename;
2754 }
2755
2756 ///////////////////////////////////////////////////////////////////////
2757 std::size_t getLine
2758 ()
2759 const
2760 {
2761 return m_line;
2762 }
2763
2764 ///////////////////////////////////////////////////////////////////////
2765 bool isHidden
2766 ()
2767 const
2768 {
2769 return m_name.size() >= 2 && m_name[0] == '.' && m_name[1] == '/';
2770 }
2771
2772 ///////////////////////////////////////////////////////////////////////
2773 void swap
2774 (
2775 TestCaseInfo& other
2776 )
2777 {
2778 std::swap( m_test, other.m_test );
2779 m_name.swap( other.m_name );
2780 m_description.swap( other.m_description );
2781 }
2782
2783 ///////////////////////////////////////////////////////////////////////
2784 bool operator ==
2785 (
2786 const TestCaseInfo& other
2787 )
2788 const
2789 {
2790 return *m_test == *other.m_test && m_name == other.m_name && m_description == other.m_description;
2791 }
2792
2793 ///////////////////////////////////////////////////////////////////////
2794 bool operator <
2795 (
2796 const TestCaseInfo& other
2797 )
2798 const
2799 {
2800 if( m_name < other.m_name )
2801 return true;
2802 if( m_name > other.m_name )
2803 return false;
2804
2805 return *m_test < *other.m_test;
2806 }
2807
2808 private:
2809 ITestCase* m_test;
2810 std::string m_name;
2811 std::string m_description;
2812 std::string m_filename;
2813 std::size_t m_line;
2814
2815 };
2816
2817 ///////////////////////////////////////////////////////////////////////////
2818 ///////////////////////////////////////////////////////////////////////////
2819
2820 class TestSpec
2821 {
2822 public:
2823 ///////////////////////////////////////////////////////////////////////
2824 TestSpec
2825 (
2826 const std::string& rawSpec
2827 )
2828 : m_rawSpec( rawSpec ),
2829 m_isWildcarded( false )
2830 {
2831 if( m_rawSpec[m_rawSpec.size()-1] == '*' )
2832 {
2833 m_rawSpec = m_rawSpec.substr( 0, m_rawSpec.size()-1 );
2834 m_isWildcarded = true;
2835 }
2836 }
2837
2838 ///////////////////////////////////////////////////////////////////////
2839 bool matches
2840 (
2841 const std::string& testName
2842 )
2843 const
2844 {
2845 if( !m_isWildcarded )
2846 return m_rawSpec == testName;
2847 else
2848 return testName.size() >= m_rawSpec.size() && testName.substr( 0, m_rawSpec.size() ) == m_rawSpec;
2849 }
2850
2851 private:
2852 std::string m_rawSpec;
2853 bool m_isWildcarded;
2854 };
2855}
2856
2857
2858#include <vector>
2859#include <set>
2860#include <sstream>
2861
2862#include <iostream> // !TBD DBG
2863namespace Catch
2864{
2865 class TestRegistry : public ITestCaseRegistry
2866 {
2867 public:
2868 ///////////////////////////////////////////////////////////////////////////
2869 TestRegistry
2870 ()
2871 : m_unnamedCount( 0 )
2872 {
2873 }
2874
2875 ///////////////////////////////////////////////////////////////////////////
2876 virtual void registerTest
2877 (
2878 const TestCaseInfo& testInfo
2879 )
2880 {
2881 if( testInfo.getName() == "" )
2882 {
2883 std::ostringstream oss;
2884 oss << testInfo.getName() << "unnamed/" << ++m_unnamedCount;
2885 return registerTest( TestCaseInfo( testInfo, oss.str() ) );
2886 }
2887 if( m_functions.find( testInfo ) == m_functions.end() )
2888 {
2889 m_functions.insert( testInfo );
2890 m_functionsInOrder.push_back( testInfo );
2891 }
2892 }
2893
2894 ///////////////////////////////////////////////////////////////////////////
2895 virtual const std::vector<TestCaseInfo>& getAllTests
2896 ()
2897 const
2898 {
2899 return m_functionsInOrder;
2900 }
2901
2902 ///////////////////////////////////////////////////////////////////////////
2903 virtual std::vector<TestCaseInfo> getMatchingTestCases
2904 (
2905 const std::string& rawTestSpec
2906 )
2907 {
2908 TestSpec testSpec( rawTestSpec );
2909
2910 std::vector<TestCaseInfo> testList;
2911 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
2912 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
2913 for(; it != itEnd; ++it )
2914 {
2915 if( testSpec.matches( it->getName() ) )
2916 {
2917 testList.push_back( *it );
2918 std::cout << it->getName() << std::endl;
2919 }
2920 }
2921 return testList;
2922 }
2923
2924 private:
2925
2926 std::set<TestCaseInfo> m_functions;
2927 std::vector<TestCaseInfo> m_functionsInOrder;
2928 size_t m_unnamedCount;
2929 };
2930
2931 ///////////////////////////////////////////////////////////////////////////
2932 ///////////////////////////////////////////////////////////////////////////
2933
2934
2935 struct FreeFunctionTestCase : ITestCase
2936 {
2937 ///////////////////////////////////////////////////////////////////////////
2938 FreeFunctionTestCase
2939 (
2940 TestFunction fun
2941 )
2942 : m_fun( fun )
2943 {}
2944
2945 ///////////////////////////////////////////////////////////////////////////
2946 virtual void invoke
2947 ()
2948 const
2949 {
2950 m_fun();
2951 }
2952
2953 ///////////////////////////////////////////////////////////////////////////
2954 virtual ITestCase* clone
2955 ()
2956 const
2957 {
2958 return new FreeFunctionTestCase( m_fun );
2959 }
2960
2961 ///////////////////////////////////////////////////////////////////////////
2962 virtual bool operator ==
2963 (
2964 const ITestCase& other
2965 )
2966 const
2967 {
2968 const FreeFunctionTestCase* ffOther = dynamic_cast<const FreeFunctionTestCase*> ( &other );
2969 return ffOther && m_fun == ffOther->m_fun;
2970 }
2971
2972 ///////////////////////////////////////////////////////////////////////////
2973 virtual bool operator <
2974 (
2975 const ITestCase& other
2976 )
2977 const
2978 {
2979 const FreeFunctionTestCase* ffOther = dynamic_cast<const FreeFunctionTestCase*> ( &other );
2980 return ffOther && m_fun < ffOther->m_fun;
2981 }
2982
2983 private:
2984 TestFunction m_fun;
2985 };
2986
2987 ///////////////////////////////////////////////////////////////////////////
2988 ///////////////////////////////////////////////////////////////////////////
2989
2990 ///////////////////////////////////////////////////////////////////////////
2991 AutoReg::AutoReg
2992 (
2993 TestFunction function,
2994 const char* name,
2995 const char* description,
2996 const char* filename,
2997 std::size_t line
2998 )
2999 {
3000 registerTestCase( new FreeFunctionTestCase( function ), name, description, filename, line );
3001 }
3002
3003 ///////////////////////////////////////////////////////////////////////////
3004 AutoReg::~AutoReg
3005 ()
3006 {
3007 }
3008
3009 ///////////////////////////////////////////////////////////////////////////
3010 void AutoReg::registerTestCase
3011 (
3012 ITestCase* testCase,
3013 const char* name,
3014 const char* description,
3015 const char* filename,
3016 std::size_t line
3017 )
3018 {
3019 Hub::getTestCaseRegistry().registerTest( TestCaseInfo( testCase, name, description, filename, line ) );
3020 }
3021
3022} // end namespace Catch
3023
3024// #included from: catch_exception_translator_registry.hpp
3025
3026/*
3027 * catch_exception_translator_registry.hpp
3028 * Catch
3029 *
3030 * Created by Phil on 20/04/2011.
3031 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
3032 *
3033 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3034 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3035 *
3036 */
3037#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_HPP_INCLUDED
3038
3039
3040namespace Catch
3041{
3042 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry
3043 {
3044 ///////////////////////////////////////////////////////////////////////
3045 virtual void registerTranslator
3046 (
3047 IExceptionTranslator* translator
3048 )
3049 {
3050 m_translators.push_back( translator );
3051 }
3052
3053 ///////////////////////////////////////////////////////////////////////
3054 virtual std::string translateActiveException
3055 ()
3056 const
3057 {
3058 return tryTranslators( m_translators.begin() );
3059 }
3060
3061 ///////////////////////////////////////////////////////////////////////
3062 std::string tryTranslators
3063 (
3064 std::vector<IExceptionTranslator*>::const_iterator it
3065 )
3066 const
3067 {
3068 if( it == m_translators.end() )
3069 return "Unknown exception";
3070
3071 try
3072 {
3073 return (*it)->translate();
3074 }
3075 catch(...)
3076 {
3077 return tryTranslators( it+1 );
3078 }
3079 }
3080
3081 private:
3082 std::vector<IExceptionTranslator*> m_translators;
3083 };
3084}
3085
3086// #included from: catch_runner_impl.hpp
3087
3088/*
3089 * catch_runner.hpp
3090 * Catch
3091 *
3092 * Created by Phil on 22/10/2010.
3093 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
3094 *
3095 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3096 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3097 *
3098 */
3099#define TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED
3100
3101// #included from: catch_interfaces_runner.h
3102
3103/*
3104 * catch_interfaces_runner.h
3105 * Catch
3106 *
3107 * Created by Phil on 07/01/2011.
3108 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
3109 *
3110 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3111 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3112 *
3113 */
3114#define TWOBLUECUBES_INTERNAL_CATCH_INTERFACES_RUNNER_H_INCLUDED
3115
3116#include <string>
3117
3118namespace Catch
3119{
3120 class TestCaseInfo;
3121
3122 struct IRunner
3123 {
3124 virtual ~IRunner
3125 ()
3126 {}
3127
3128 virtual void runAll
3129 ( bool runHiddenTests = false
3130 ) = 0;
3131
3132 virtual std::size_t runMatching
3133 ( const std::string& rawTestSpec
3134 ) = 0;
3135
3136 virtual std::size_t getSuccessCount
3137 () const = 0;
3138
3139 virtual std:: size_t getFailureCount
3140 () const = 0;
3141
3142 };
3143}
3144
3145// #included from: catch_config.hpp
3146
3147/*
3148 * catch_config.hpp
3149 * Catch
3150 *
3151 * Created by Phil on 08/11/2010.
3152 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
3153 *
3154 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3155 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3156 *
3157 */
3158
3159#define TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
3160
3161
3162#include <memory>
3163#include <vector>
3164#include <string>
3165#include <iostream>
3166
3167namespace Catch
3168{
3169
3170 class Config : public IReporterConfig
3171 {
3172 private:
3173 Config( const Config& other );
3174 Config& operator = ( const Config& other );
3175 public:
3176
3177 struct Include { enum What
3178 {
3179 FailedOnly,
3180 SuccessfulResults
3181 }; };
3182
3183 struct List{ enum What
3184 {
3185 None = 0,
3186
3187 Reports = 1,
3188 Tests = 2,
3189 All = 3,
3190
3191 WhatMask = 0xf,
3192
3193 AsText = 0x10,
3194 AsXml = 0x11,
3195
3196 AsMask = 0xf0
3197 }; };
3198
3199
3200 ///////////////////////////////////////////////////////////////////////////
3201 Config()
3202 : m_reporter( NULL ),
3203 m_listSpec( List::None ),
3204 m_shouldDebugBreak( false ),
3205 m_showHelp( false ),
Phil Nash48112c22011-05-31 18:47:30 +01003206 m_streambuf( NULL ),
3207 m_os( std::cout.rdbuf() ),
Phil Nash89d1e6c2011-05-24 08:23:02 +01003208 m_includeWhat( Include::FailedOnly )
3209 {}
3210
3211 ///////////////////////////////////////////////////////////////////////////
3212 ~Config()
3213 {
Phil Nash48112c22011-05-31 18:47:30 +01003214 m_os.rdbuf( std::cout.rdbuf() );
3215 delete m_streambuf;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003216 }
3217
3218 ///////////////////////////////////////////////////////////////////////////
3219 void setReporter( const std::string& reporterName )
3220 {
3221 if( m_reporter.get() )
3222 return setError( "Only one reporter may be specified" );
3223 setReporter( Hub::getReporterRegistry().create( reporterName, *this ) );
3224 }
3225
3226 ///////////////////////////////////////////////////////////////////////////
3227 void addTestSpec( const std::string& testSpec )
3228 {
3229 m_testSpecs.push_back( testSpec );
3230 }
3231
3232 ///////////////////////////////////////////////////////////////////////////
3233 bool testsSpecified() const
3234 {
3235 return !m_testSpecs.empty();
3236 }
3237
3238 ///////////////////////////////////////////////////////////////////////////
3239 const std::vector<std::string>& getTestSpecs() const
3240 {
3241 return m_testSpecs;
3242 }
3243
3244 ///////////////////////////////////////////////////////////////////////////
3245 List::What getListSpec( void ) const
3246 {
3247 return m_listSpec;
3248 }
3249
3250 ///////////////////////////////////////////////////////////////////////////
3251 void setListSpec( List::What listSpec )
3252 {
3253 m_listSpec = listSpec;
3254 }
3255
3256 ///////////////////////////////////////////////////////////////////////////
3257 void setFilename( const std::string& filename )
3258 {
3259 m_filename = filename;
3260 }
3261
3262 ///////////////////////////////////////////////////////////////////////////
3263 const std::string& getFilename() const
3264 {
3265 return m_filename;
3266 }
3267
3268 ///////////////////////////////////////////////////////////////////////////
3269 const std::string& getMessage() const
3270 {
3271 return m_message;
3272 }
3273
3274 ///////////////////////////////////////////////////////////////////////////
3275 void setError( const std::string& errorMessage )
3276 {
3277 m_message = errorMessage + "\n\n" + "Usage: ...";
3278 }
3279
3280 ///////////////////////////////////////////////////////////////////////////
3281 void setReporter( IReporter* reporter )
3282 {
3283 m_reporter = std::auto_ptr<IReporter>( reporter );
3284 }
3285
3286 ///////////////////////////////////////////////////////////////////////////
3287 IReporter* getReporter() const
3288 {
3289 if( !m_reporter.get() )
3290 const_cast<Config*>( this )->setReporter( Hub::getReporterRegistry().create( "basic", *this ) );
3291 return m_reporter.get();
3292 }
3293
3294 ///////////////////////////////////////////////////////////////////////////
3295 List::What listWhat() const
3296 {
3297 return static_cast<List::What>( m_listSpec & List::WhatMask );
3298 }
3299
3300 ///////////////////////////////////////////////////////////////////////////
3301 List::What listAs() const
3302 {
3303 return static_cast<List::What>( m_listSpec & List::AsMask );
3304 }
3305
3306 ///////////////////////////////////////////////////////////////////////////
3307 void setIncludeWhat( Include::What includeWhat )
3308 {
3309 m_includeWhat = includeWhat;
3310 }
3311
3312 ///////////////////////////////////////////////////////////////////////////
3313 void setShouldDebugBreak( bool shouldDebugBreakFlag )
3314 {
3315 m_shouldDebugBreak = shouldDebugBreakFlag;
3316 }
3317
3318 ///////////////////////////////////////////////////////////////////////////
3319 void setName( const std::string& name )
3320 {
3321 m_name = name;
3322 }
3323
3324 ///////////////////////////////////////////////////////////////////////////
3325 std::string getName() const
3326 {
3327 return m_name;
3328 }
3329
3330 ///////////////////////////////////////////////////////////////////////////
3331 bool shouldDebugBreak() const
3332 {
3333 return m_shouldDebugBreak;
3334 }
3335
3336 ///////////////////////////////////////////////////////////////////////////
3337 void setShowHelp( bool showHelpFlag )
3338 {
3339 m_showHelp = showHelpFlag;
3340 }
3341
3342 ///////////////////////////////////////////////////////////////////////////
3343 bool showHelp() const
3344 {
3345 return m_showHelp;
3346 }
3347
3348 ///////////////////////////////////////////////////////////////////////////
3349 virtual std::ostream& stream() const
3350 {
3351 return m_os;
3352 }
3353
3354 ///////////////////////////////////////////////////////////////////////////
3355 void setStreamBuf( std::streambuf* buf )
3356 {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003357 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
3358 }
3359
3360 ///////////////////////////////////////////////////////////////////////////
3361 void useStream( const std::string& streamName )
3362 {
Phil Nash48112c22011-05-31 18:47:30 +01003363 std::streambuf* newBuf = Hub::createStreamBuf( streamName );
3364 setStreamBuf( newBuf );
3365 delete m_streambuf;
3366 m_streambuf = newBuf;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003367 }
3368
3369 ///////////////////////////////////////////////////////////////////////////
3370 virtual bool includeSuccessfulResults() const
3371 {
3372 return m_includeWhat == Include::SuccessfulResults;
3373 }
3374
3375 private:
3376 std::auto_ptr<IReporter> m_reporter;
3377 std::string m_filename;
3378 std::string m_message;
3379 List::What m_listSpec;
3380 std::vector<std::string> m_testSpecs;
3381 bool m_shouldDebugBreak;
3382 bool m_showHelp;
3383 std::streambuf* m_streambuf;
3384 mutable std::ostream m_os;
3385 Include::What m_includeWhat;
3386 std::string m_name;
3387
3388 };
3389
3390} // end namespace Catch
3391
3392
3393#include <set>
3394#include <string>
3395
3396namespace Catch
3397{
3398
3399 class StreamRedirect
3400 {
3401 public:
3402 ///////////////////////////////////////////////////////////////////////
3403 StreamRedirect
3404 (
3405 std::ostream& stream,
3406 std::string& targetString
3407 )
3408 : m_stream( stream ),
3409 m_prevBuf( stream.rdbuf() ),
3410 m_targetString( targetString )
3411 {
3412 stream.rdbuf( m_oss.rdbuf() );
3413 }
3414
3415 ///////////////////////////////////////////////////////////////////////
3416 ~StreamRedirect
3417 ()
3418 {
3419 m_targetString = m_oss.str();
3420 m_stream.rdbuf( m_prevBuf );
3421 }
3422
3423 private:
3424 std::ostream& m_stream;
3425 std::streambuf* m_prevBuf;
3426 std::ostringstream m_oss;
3427 std::string& m_targetString;
3428 };
3429
3430
3431 ///////////////////////////////////////////////////////////////////////////
3432 ///////////////////////////////////////////////////////////////////////////
3433 class SectionInfo
3434 {
3435 public:
3436 enum Status
3437 {
3438 Root,
3439 Unknown,
3440 NonLeaf,
Phil Nash89d1e6c2011-05-24 08:23:02 +01003441 TestedLeaf
3442 };
3443
3444 ///////////////////////////////////////////////////////////////////////
3445 SectionInfo
3446 (
3447 SectionInfo* parent
3448 )
3449 : m_status( Unknown ),
3450 m_parent( parent )
3451 {
3452 }
3453
3454 ///////////////////////////////////////////////////////////////////////
3455 SectionInfo
3456 ()
3457 : m_status( Root ),
3458 m_parent( NULL )
3459 {
3460 }
3461
3462 ///////////////////////////////////////////////////////////////////////
3463 ~SectionInfo
3464 ()
3465 {
3466 deleteAllValues( m_subSections );
3467 }
3468
3469 ///////////////////////////////////////////////////////////////////////
3470 bool shouldRun
3471 ()
3472 const
3473 {
3474 return m_status != TestedLeaf;
3475 }
3476
3477 ///////////////////////////////////////////////////////////////////////
3478 bool ran
3479 ()
3480 {
3481 if( m_status != NonLeaf )
3482 {
3483 m_status = TestedLeaf;
3484 return true;
3485 }
3486 return false;
3487 }
3488
3489 ///////////////////////////////////////////////////////////////////////
Phil Nash3c20a752011-06-23 08:23:33 +01003490 SectionInfo* findSubSection
Phil Nash89d1e6c2011-05-24 08:23:02 +01003491 (
3492 const std::string& name
3493 )
3494 {
3495 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.find( name );
Phil Nash3c20a752011-06-23 08:23:33 +01003496 return it != m_subSections.end()
3497 ? it->second
3498 : NULL;
3499 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003500
Phil Nash3c20a752011-06-23 08:23:33 +01003501 ///////////////////////////////////////////////////////////////////////
3502 SectionInfo* addSubSection
3503 (
3504 const std::string& name
3505 )
3506 {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003507 SectionInfo* subSection = new SectionInfo( this );
3508 m_subSections.insert( std::make_pair( name, subSection ) );
3509 m_status = NonLeaf;
3510 return subSection;
3511 }
3512
3513 ///////////////////////////////////////////////////////////////////////
3514 SectionInfo* getParent
3515 ()
3516 {
3517 return m_parent;
3518 }
3519
3520 ///////////////////////////////////////////////////////////////////////
3521 bool hasUntestedSections
3522 ()
3523 const
3524 {
Phil Nash3c20a752011-06-23 08:23:33 +01003525 if( m_status == Unknown )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003526 return true;
3527
3528 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.begin();
3529 std::map<std::string, SectionInfo*>::const_iterator itEnd = m_subSections.end();
3530 for(; it != itEnd; ++it )
3531 {
3532 if( it->second->hasUntestedSections() )
3533 return true;
3534 }
3535 return false;
3536 }
3537
3538 private:
3539 Status m_status;
3540 std::map<std::string, SectionInfo*> m_subSections;
3541 SectionInfo* m_parent;
3542 };
3543
3544 ///////////////////////////////////////////////////////////////////////////
3545 ///////////////////////////////////////////////////////////////////////////
3546
3547 class RunningTest
3548 {
3549 enum RunStatus
3550 {
3551 NothingRun,
3552 EncounteredASection,
3553 RanAtLeastOneSection,
3554 RanToCompletionWithSections,
3555 RanToCompletionWithNoSections
3556 };
3557
3558 public:
3559 ///////////////////////////////////////////////////////////////////////
3560 explicit RunningTest
3561 (
3562 const TestCaseInfo* info = NULL
3563 )
3564 : m_info( info ),
3565 m_runStatus( RanAtLeastOneSection ),
Phil Nash3c20a752011-06-23 08:23:33 +01003566 m_currentSection( &m_rootSection ),
3567 m_changed( false )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003568 {
3569 }
3570
3571 ///////////////////////////////////////////////////////////////////////
3572 bool wasSectionSeen
3573 ()
3574 const
3575 {
3576 return m_runStatus == RanAtLeastOneSection ||
3577 m_runStatus == RanToCompletionWithSections;
3578 }
3579
3580 ///////////////////////////////////////////////////////////////////////
3581 void reset
3582 ()
3583 {
3584 m_runStatus = NothingRun;
Phil Nash3c20a752011-06-23 08:23:33 +01003585 m_changed = false;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003586 }
3587
3588 ///////////////////////////////////////////////////////////////////////
3589 void ranToCompletion
3590 ()
3591 {
3592 m_runStatus = m_runStatus == RanAtLeastOneSection ||
3593 m_runStatus == EncounteredASection
3594 ? RanToCompletionWithSections
3595 : RanToCompletionWithNoSections;
3596 }
3597
3598 ///////////////////////////////////////////////////////////////////////
3599 bool addSection
3600 (
3601 const std::string& name
3602 )
3603 {
3604 if( m_runStatus == NothingRun )
3605 m_runStatus = EncounteredASection;
3606
Phil Nash3c20a752011-06-23 08:23:33 +01003607 SectionInfo* thisSection = m_currentSection->findSubSection( name );
3608 if( !thisSection )
3609 {
3610 thisSection = m_currentSection->addSubSection( name );
3611 m_changed = true;
3612 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003613
3614 if( !wasSectionSeen() && thisSection->shouldRun() )
3615 {
3616 m_currentSection = thisSection;
3617 return true;
3618 }
3619 return false;
3620 }
3621
3622 ///////////////////////////////////////////////////////////////////////
3623 void endSection
3624 (
3625 const std::string&
3626 )
3627 {
3628 if( m_currentSection->ran() )
Phil Nash3c20a752011-06-23 08:23:33 +01003629 {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003630 m_runStatus = RanAtLeastOneSection;
Phil Nash3c20a752011-06-23 08:23:33 +01003631 m_changed = true;
3632 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003633 m_currentSection = m_currentSection->getParent();
3634 }
3635
3636 ///////////////////////////////////////////////////////////////////////
3637 const TestCaseInfo& getTestCaseInfo
3638 ()
3639 const
3640 {
3641 return *m_info;
3642 }
3643
3644 ///////////////////////////////////////////////////////////////////////
3645 bool hasUntestedSections
3646 ()
3647 const
3648 {
Phil Nash3c20a752011-06-23 08:23:33 +01003649 return m_runStatus == RanAtLeastOneSection ||
3650 ( m_rootSection.hasUntestedSections() && m_changed );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003651 }
3652
3653 private:
3654 const TestCaseInfo* m_info;
3655 RunStatus m_runStatus;
3656 SectionInfo m_rootSection;
3657 SectionInfo* m_currentSection;
Phil Nash3c20a752011-06-23 08:23:33 +01003658 bool m_changed;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003659 };
3660
3661 ///////////////////////////////////////////////////////////////////////////
3662 ///////////////////////////////////////////////////////////////////////////
3663 class Runner : public IResultCapture, public IRunner
3664 {
3665 Runner( const Runner& );
3666 void operator =( const Runner& );
3667
3668 public:
3669
3670 ///////////////////////////////////////////////////////////////////////////
3671 explicit Runner
3672 (
3673 const Config& config
3674 )
3675 : m_runningTest( NULL ),
3676 m_config( config ),
3677 m_successes( 0 ),
3678 m_failures( 0 ),
3679 m_reporter( m_config.getReporter() ),
3680 m_prevRunner( &Hub::getRunner() ),
3681 m_prevResultCapture( &Hub::getResultCapture() )
3682 {
3683 Hub::setRunner( this );
3684 Hub::setResultCapture( this );
3685 m_reporter->StartTesting();
3686 }
3687
3688 ///////////////////////////////////////////////////////////////////////////
3689 ~Runner
3690 ()
3691 {
3692 m_reporter->EndTesting( m_successes, m_failures );
3693 Hub::setRunner( m_prevRunner );
3694 Hub::setResultCapture( m_prevResultCapture );
3695 }
3696
3697 ///////////////////////////////////////////////////////////////////////////
3698 virtual void runAll
3699 (
3700 bool runHiddenTests = false
3701 )
3702 {
3703 std::vector<TestCaseInfo> allTests = Hub::getTestCaseRegistry().getAllTests();
3704 for( std::size_t i=0; i < allTests.size(); ++i )
3705 {
3706 if( runHiddenTests || !allTests[i].isHidden() )
3707 runTest( allTests[i] );
3708 }
3709 }
3710
3711 ///////////////////////////////////////////////////////////////////////////
3712 virtual std::size_t runMatching
3713 (
3714 const std::string& rawTestSpec
3715 )
3716 {
3717 TestSpec testSpec( rawTestSpec );
3718
3719 std::vector<TestCaseInfo> allTests = Hub::getTestCaseRegistry().getAllTests();
3720 std::size_t testsRun = 0;
3721 for( std::size_t i=0; i < allTests.size(); ++i )
3722 {
3723 if( testSpec.matches( allTests[i].getName() ) )
3724 {
3725 runTest( allTests[i] );
3726 testsRun++;
3727 }
3728 }
3729 return testsRun;
3730 }
3731
3732 ///////////////////////////////////////////////////////////////////////////
3733 void runTest
3734 (
3735 const TestCaseInfo& testInfo
3736 )
3737 {
3738 std::size_t prevSuccessCount = m_successes;
3739 std::size_t prevFailureCount = m_failures;
3740
3741 std::string redirectedCout;
3742 std::string redirectedCerr;
3743
3744 m_reporter->StartTestCase( testInfo );
3745
3746 m_runningTest = new RunningTest( &testInfo );
3747
3748 do
3749 {
3750 do
3751 {
3752 m_currentResult.setFileAndLine( m_runningTest->getTestCaseInfo().getFilename(),
3753 m_runningTest->getTestCaseInfo().getLine() );
3754 runCurrentTest( redirectedCout, redirectedCerr );
3755 }
3756 while( m_runningTest->hasUntestedSections() );
3757 }
3758 while( Hub::advanceGeneratorsForCurrentTest() );
3759
3760 delete m_runningTest;
3761 m_runningTest = NULL;
3762
3763 m_reporter->EndTestCase( testInfo, m_successes - prevSuccessCount, m_failures - prevFailureCount, redirectedCout, redirectedCerr );
3764 }
3765
3766 ///////////////////////////////////////////////////////////////////////////
3767 virtual std::size_t getSuccessCount
3768 ()
3769 const
3770 {
3771 return m_successes;
3772 }
3773
3774 ///////////////////////////////////////////////////////////////////////////
3775 virtual std:: size_t getFailureCount
3776 ()
3777 const
3778 {
3779 return m_failures;
3780 }
3781
3782 private: // IResultCapture
3783
3784 ///////////////////////////////////////////////////////////////////////////
3785 virtual ResultAction::Value acceptResult
3786 (
3787 bool result
3788 )
3789 {
3790 return acceptResult( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
3791 }
3792
3793 ///////////////////////////////////////////////////////////////////////////
3794 virtual ResultAction::Value acceptResult
3795 (
3796 ResultWas::OfType result
3797 )
3798 {
3799 m_currentResult.setResultType( result );
3800 return actOnCurrentResult();
3801 }
3802
3803 ///////////////////////////////////////////////////////////////////////////
3804 virtual ResultAction::Value acceptExpression
3805 (
3806 const MutableResultInfo& resultInfo
3807 )
3808 {
3809 m_currentResult = resultInfo;
3810 return actOnCurrentResult();
3811 }
3812
3813 ///////////////////////////////////////////////////////////////////////////
3814 virtual void acceptMessage
3815 (
3816 const std::string& msg
3817 )
3818 {
3819 m_currentResult.setMessage( msg );
3820 }
3821
3822 ///////////////////////////////////////////////////////////////////////////
3823 virtual void testEnded
3824 (
3825 const ResultInfo& result
3826 )
3827 {
3828 if( result.getResultType() == ResultWas::Ok )
3829 {
3830 m_successes++;
3831 }
3832 else if( !result.ok() )
3833 {
3834 m_failures++;
3835
3836 std::vector<ResultInfo>::const_iterator it = m_info.begin();
3837 std::vector<ResultInfo>::const_iterator itEnd = m_info.end();
3838 for(; it != itEnd; ++it )
3839 m_reporter->Result( *it );
3840 m_info.clear();
3841 }
3842
3843 if( result.getResultType() == ResultWas::Info )
3844 m_info.push_back( result );
3845 else
3846 m_reporter->Result( result );
3847 }
3848
3849 ///////////////////////////////////////////////////////////////////////////
3850 virtual bool sectionStarted
3851 (
3852 const std::string& name,
3853 const std::string& description,
3854 const std::string& filename,
3855 std::size_t line,
3856 std::size_t& successes,
3857 std::size_t& failures
3858 )
3859 {
3860 std::ostringstream oss;
3861 oss << filename << ":" << line;
3862
3863 if( !m_runningTest->addSection( oss.str() ) )
3864 return false;
3865
3866 m_currentResult.setFileAndLine( filename, line );
3867 m_reporter->StartSection( name, description );
3868 successes = m_successes;
3869 failures = m_failures;
3870
3871 return true;
3872 }
3873
3874 ///////////////////////////////////////////////////////////////////////////
3875 virtual void sectionEnded
3876 (
3877 const std::string& name,
3878 std::size_t prevSuccesses,
3879 std::size_t prevFailures
3880 )
3881 {
3882 m_runningTest->endSection( name );
3883 m_reporter->EndSection( name, m_successes - prevSuccesses, m_failures - prevFailures );
3884 }
3885
3886 ///////////////////////////////////////////////////////////////////////////
3887 virtual void pushScopedInfo
3888 (
3889 ScopedInfo* scopedInfo
3890 )
3891 {
3892 m_scopedInfos.push_back( scopedInfo );
3893 }
3894
3895 ///////////////////////////////////////////////////////////////////////////
3896 virtual void popScopedInfo
3897 (
3898 ScopedInfo* scopedInfo
3899 )
3900 {
3901 if( m_scopedInfos.back() == scopedInfo )
3902 m_scopedInfos.pop_back();
3903 }
3904
3905 ///////////////////////////////////////////////////////////////////////////
3906 virtual bool shouldDebugBreak
3907 ()
3908 const
3909 {
3910 return m_config.shouldDebugBreak();
3911 }
3912
3913 ///////////////////////////////////////////////////////////////////////////
3914 virtual std::string getCurrentTestName
3915 ()
3916 const
3917 {
3918 return m_runningTest
3919 ? m_runningTest->getTestCaseInfo().getName()
3920 : "";
3921 }
3922
3923 private:
3924
3925 ///////////////////////////////////////////////////////////////////////////
3926 ResultAction::Value actOnCurrentResult
3927 ()
3928 {
3929 testEnded( m_currentResult );
3930
3931 bool ok = m_currentResult.ok();
3932 m_currentResult = MutableResultInfo();
3933 if( ok )
3934 return ResultAction::None;
3935 else if( shouldDebugBreak() )
3936 return ResultAction::DebugFailed;
3937 else
3938 return ResultAction::Failed;
3939 }
3940
3941 ///////////////////////////////////////////////////////////////////////////
3942 void runCurrentTest
3943 (
3944 std::string& redirectedCout,
3945 std::string& redirectedCerr
3946 )
3947 {
3948 try
3949 {
3950 m_runningTest->reset();
3951 StreamRedirect coutRedir( std::cout, redirectedCout );
3952 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
3953 m_runningTest->getTestCaseInfo().invoke();
3954 m_runningTest->ranToCompletion();
3955 }
3956 catch( TestFailureException& )
3957 {
3958 // This just means the test was aborted due to failure
3959 }
3960 catch( std::exception& ex )
3961 {
3962 acceptMessage( ex.what() );
3963 acceptResult( ResultWas::ThrewException );
3964 }
3965 catch( std::string& msg )
3966 {
3967 acceptMessage( msg );
3968 acceptResult( ResultWas::ThrewException );
3969 }
3970 catch( const char* msg )
3971 {
3972 acceptMessage( msg );
3973 acceptResult( ResultWas::ThrewException );
3974 }
3975 catch(...)
3976 {
3977 acceptMessage( Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() );
3978 acceptResult( ResultWas::ThrewException );
3979 }
3980 m_info.clear();
3981 }
3982
3983 private:
3984 RunningTest* m_runningTest;
3985 MutableResultInfo m_currentResult;
3986
3987 const Config& m_config;
3988 std::size_t m_successes;
3989 std::size_t m_failures;
3990 IReporter* m_reporter;
3991 std::vector<ScopedInfo*> m_scopedInfos;
3992 std::vector<ResultInfo> m_info;
3993 IRunner* m_prevRunner;
3994 IResultCapture* m_prevResultCapture;
3995 };
3996}
3997
3998// #included from: catch_generators_impl.hpp
3999
4000/*
4001 * catch_generators_impl.hpp
4002 * Catch
4003 *
4004 * Created by Phil on 28/01/2011.
4005 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
4006 *
4007 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4008 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4009 *
4010 */
4011
4012#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
4013
4014
4015#include <vector>
4016#include <string>
4017#include <map>
4018
4019namespace Catch
4020{
4021 struct GeneratorInfo
4022 {
4023 ///////////////////////////////////////////////////////////////////////
4024 GeneratorInfo
4025 (
4026 std::size_t size
4027 )
4028 : m_size( size ),
4029 m_currentIndex( 0 )
4030 {
4031 }
4032
4033 ///////////////////////////////////////////////////////////////////////
4034 bool moveNext
4035 ()
4036 {
4037 if( ++m_currentIndex == m_size )
4038 {
4039 m_currentIndex = 0;
4040 return false;
4041 }
4042 return true;
4043 }
4044
4045 ///////////////////////////////////////////////////////////////////////
4046 std::size_t getCurrentIndex
4047 ()
4048 const
4049 {
4050 return m_currentIndex;
4051 }
4052
4053 std::size_t m_size;
4054 std::size_t m_currentIndex;
4055 };
4056
4057 ///////////////////////////////////////////////////////////////////////////
4058 ///////////////////////////////////////////////////////////////////////////
4059
4060 class GeneratorsForTest
4061 {
4062
4063 public:
4064 ///////////////////////////////////////////////////////////////////////
4065 ~GeneratorsForTest
4066 ()
4067 {
4068 deleteAll( m_generatorsInOrder );
4069 }
4070
4071 ///////////////////////////////////////////////////////////////////////
4072 GeneratorInfo& getGeneratorInfo
4073 (
4074 const std::string& fileInfo,
4075 std::size_t size
4076 )
4077 {
4078 std::map<std::string, GeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
4079 if( it == m_generatorsByName.end() )
4080 {
4081 GeneratorInfo* info = new GeneratorInfo( size );
4082 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
4083 m_generatorsInOrder.push_back( info );
4084 return *info;
4085 }
4086 return *it->second;
4087 }
4088
4089 ///////////////////////////////////////////////////////////////////////
4090 bool moveNext
4091 ()
4092 {
4093 std::vector<GeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
4094 std::vector<GeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
4095 for(; it != itEnd; ++it )
4096 {
4097 if( (*it)->moveNext() )
4098 return true;
4099 }
4100 return false;
4101 }
4102
4103 private:
4104 std::map<std::string, GeneratorInfo*> m_generatorsByName;
4105 std::vector<GeneratorInfo*> m_generatorsInOrder;
4106 };
4107
4108} // end namespace Catch
4109
4110#define INTERNAL_CATCH_LINESTR2( line ) #line
4111#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
4112
4113#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
4114
4115// #included from: catch_stream.hpp
4116
4117/*
4118 * catch_stream.hpp
4119 * Catch
4120 *
4121 * Created by Phil on 17/01/2011.
4122 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
4123 *
4124 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4125 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4126 *
4127 */
4128
4129#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
4130
4131#include <stdexcept>
4132#include <cstdio>
4133
4134namespace Catch
4135{
4136 template<typename WriterF, size_t bufferSize=256>
4137 class StreamBufImpl : public StreamBufBase
4138 {
4139 char data[bufferSize];
4140 WriterF m_writer;
4141
4142 public:
4143 ///////////////////////////////////////////////////////////////////////
4144 StreamBufImpl
4145 ()
4146 {
4147 setp( data, data + sizeof(data) );
4148 }
4149
4150 ///////////////////////////////////////////////////////////////////////
4151 ~StreamBufImpl
4152 ()
4153 {
4154 sync();
4155 }
4156
4157 private:
4158 ///////////////////////////////////////////////////////////////////////
4159 int overflow
4160 (
4161 int c
4162 )
4163 {
4164 sync();
4165
4166 if( c != EOF )
4167 {
4168 if( pbase() == epptr() )
4169 m_writer( std::string( 1, static_cast<char>( c ) ) );
4170 else
4171 sputc( static_cast<char>( c ) );
4172 }
4173 return 0;
4174 }
4175
4176 ///////////////////////////////////////////////////////////////////////
4177 int sync
4178 ()
4179 {
4180 if( pbase() != pptr() )
4181 {
4182 m_writer( std::string( pbase(), pptr() - pbase() ) );
4183 setp( pbase(), epptr() );
4184 }
4185 return 0;
4186 }
4187 };
4188
4189 ///////////////////////////////////////////////////////////////////////////
4190 ///////////////////////////////////////////////////////////////////////////
4191
4192 struct OutputDebugWriter
4193 {
4194 ///////////////////////////////////////////////////////////////////////
4195 void operator()
4196 (
4197 const std::string &str
4198 )
4199 {
4200 writeToDebugConsole( str );
4201 }
4202 };
4203}
4204
4205
4206namespace Catch
4207{
4208 ///////////////////////////////////////////////////////////////////////////
4209 Hub::Hub
4210 ()
4211 : m_reporterRegistry( new ReporterRegistry ),
4212 m_testCaseRegistry( new TestRegistry ),
4213 m_exceptionTranslatorRegistry( new ExceptionTranslatorRegistry )
4214 {
4215 }
4216
4217 ///////////////////////////////////////////////////////////////////////////
4218 Hub& Hub::me
4219 ()
4220 {
4221 static Hub hub;
4222 return hub;
4223 }
4224
4225 ///////////////////////////////////////////////////////////////////////////
4226 void Hub::setRunner( IRunner* runner )
4227 {
4228 me().m_runner = runner;
4229 }
4230 ///////////////////////////////////////////////////////////////////////////
4231 void Hub::setResultCapture( IResultCapture* resultCapture )
4232 {
4233 me().m_resultCapture = resultCapture;
4234 }
4235
4236 ///////////////////////////////////////////////////////////////////////////
4237 IResultCapture& Hub::getResultCapture
4238 ()
4239 {
4240 return *me().m_resultCapture;
4241 }
4242
4243 ///////////////////////////////////////////////////////////////////////////
4244 IRunner& Hub::getRunner
4245 ()
4246 {
4247 return *me().m_runner;
4248 }
4249
4250 ///////////////////////////////////////////////////////////////////////////
4251 IReporterRegistry& Hub::getReporterRegistry
4252 ()
4253 {
4254 return *me().m_reporterRegistry.get();
4255 }
4256
4257 ///////////////////////////////////////////////////////////////////////////
4258 ITestCaseRegistry& Hub::getTestCaseRegistry
4259 ()
4260 {
4261 return *me().m_testCaseRegistry.get();
4262 }
4263
4264 ///////////////////////////////////////////////////////////////////////////
4265 IExceptionTranslatorRegistry& Hub::getExceptionTranslatorRegistry
4266 ()
4267 {
4268 return *me().m_exceptionTranslatorRegistry.get();
4269 }
4270
4271 ///////////////////////////////////////////////////////////////////////////
4272 std::streambuf* Hub::createStreamBuf
4273 (
4274 const std::string& streamName
4275 )
4276 {
4277 if( streamName == "stdout" ) return std::cout.rdbuf();
4278 if( streamName == "stderr" ) return std::cerr.rdbuf();
4279 if( streamName == "debug" ) return new StreamBufImpl<OutputDebugWriter>;
4280
4281 throw std::domain_error( "Unknown stream: " + streamName );
4282 }
4283
4284 ///////////////////////////////////////////////////////////////////////////
4285 GeneratorsForTest* Hub::findGeneratorsForCurrentTest
4286 ()
4287 {
4288 std::string testName = getResultCapture().getCurrentTestName();
4289
4290 std::map<std::string, GeneratorsForTest*>::const_iterator it =
4291 m_generatorsByTestName.find( testName );
4292 return it != m_generatorsByTestName.end()
4293 ? it->second
4294 : NULL;
4295 }
4296 ///////////////////////////////////////////////////////////////////////////
4297 GeneratorsForTest& Hub::getGeneratorsForCurrentTest
4298 ()
4299 {
4300 GeneratorsForTest* generators = findGeneratorsForCurrentTest();
4301 if( !generators )
4302 {
4303 std::string testName = getResultCapture().getCurrentTestName();
4304 generators = new GeneratorsForTest();
4305 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
4306 }
4307 return *generators;
4308 }
4309
4310 ///////////////////////////////////////////////////////////////////////////
4311 size_t Hub::getGeneratorIndex
4312 (
4313 const std::string& fileInfo,
4314 size_t totalSize
4315 )
4316 {
4317 return me().getGeneratorsForCurrentTest()
4318 .getGeneratorInfo( fileInfo, totalSize )
4319 .getCurrentIndex();
4320 }
4321
4322 ///////////////////////////////////////////////////////////////////////////
4323 bool Hub::advanceGeneratorsForCurrentTest
4324 ()
4325 {
4326 GeneratorsForTest* generators = me().findGeneratorsForCurrentTest();
4327 return generators && generators->moveNext();
4328 }
4329}
4330
4331// #included from: internal/catch_commandline.hpp
4332
4333/*
4334 * catch_commandline.hpp
4335 * Catch
4336 *
4337 * Created by Phil on 02/11/2010.
4338 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
4339 *
4340 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4341 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4342 *
4343 */
4344
4345#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
4346
4347
4348namespace Catch
4349{
4350 // !TBD: This could be refactored to be more "declarative"
4351 // have a table up front that relates the mode, option strings, # arguments, names of arguments
4352 // - may not be worth it at this scale
4353
4354 // -l, --list tests [xml] lists available tests (optionally in xml)
4355 // -l, --list reporters [xml] lists available reports (optionally in xml)
4356 // -l, --list all [xml] lists available tests and reports (optionally in xml)
4357 // -t, --test "testspec" ["testspec", ...]
4358 // -r, --reporter <type>
4359 // -o, --out filename to write to
4360 // -s, --success report successful cases too
4361 // -b, --break breaks into debugger on test failure
4362 // -n, --name specifies an optional name for the test run
4363 class ArgParser : NonCopyable
4364 {
4365 enum Mode
4366 {
4367 modeNone,
4368 modeList,
4369 modeTest,
4370 modeReport,
4371 modeOutput,
4372 modeSuccess,
4373 modeBreak,
4374 modeName,
4375 modeHelp,
4376
4377 modeError
4378 };
4379
4380 public:
4381 ///////////////////////////////////////////////////////////////////////
4382 ArgParser
4383 (
4384 int argc,
4385 char * const argv[],
4386 Config& config
4387 )
4388 : m_mode( modeNone ),
4389 m_config( config )
4390 {
4391 for( int i=1; i < argc; ++i )
4392 {
4393 if( argv[i][0] == '-' )
4394 {
4395 std::string cmd = ( argv[i] );
4396 if( cmd == "-l" || cmd == "--list" )
4397 changeMode( cmd, modeList );
4398 else if( cmd == "-t" || cmd == "--test" )
4399 changeMode( cmd, modeTest );
4400 else if( cmd == "-r" || cmd == "--reporter" )
4401 changeMode( cmd, modeReport );
4402 else if( cmd == "-o" || cmd == "--out" )
4403 changeMode( cmd, modeOutput );
4404 else if( cmd == "-s" || cmd == "--success" )
4405 changeMode( cmd, modeSuccess );
4406 else if( cmd == "-b" || cmd == "--break" )
4407 changeMode( cmd, modeBreak );
4408 else if( cmd == "-n" || cmd == "--name" )
4409 changeMode( cmd, modeName );
4410 else if( cmd == "-h" || cmd == "-?" || cmd == "--help" )
4411 changeMode( cmd, modeHelp );
4412 }
4413 else
4414 {
4415 m_args.push_back( argv[i] );
4416 }
4417 if( m_mode == modeError )
4418 return;
4419 }
4420 changeMode( "", modeNone );
4421 }
4422
4423 private:
4424 ///////////////////////////////////////////////////////////////////////
4425 std::string argsAsString
4426 ()
4427 {
4428 std::ostringstream oss;
4429 std::vector<std::string>::const_iterator it = m_args.begin();
4430 std::vector<std::string>::const_iterator itEnd = m_args.end();
4431 for( bool first = true; it != itEnd; ++it, first = false )
4432 {
4433 if( !first )
4434 oss << " ";
4435 oss << *it;
4436 }
4437 return oss.str();
4438 }
4439
4440 ///////////////////////////////////////////////////////////////////////
4441 void changeMode
4442 (
4443 const std::string& cmd,
4444 Mode mode
4445 )
4446 {
4447 m_command = cmd;
4448 switch( m_mode )
4449 {
4450 case modeNone:
4451 if( m_args.size() > 0 )
4452 return setErrorMode( "Unexpected arguments before " + m_command + ": " + argsAsString() );
4453 break;
4454 case modeList:
4455 if( m_args.size() > 2 )
4456 {
4457 return setErrorMode( m_command + " expected upto 2 arguments but recieved: " + argsAsString() );
4458 }
4459 else
4460 {
4461 Config::List::What listSpec = Config::List::All;
4462 if( m_args.size() >= 1 )
4463 {
4464 if( m_args[0] == "tests" )
4465 listSpec = Config::List::Tests;
4466 else if( m_args[0] == "reporters" )
4467 listSpec = Config::List::Reports;
4468 else
4469 return setErrorMode( m_command + " expected [tests] or [reporters] but recieved: [" + m_args[0] + "]" );
4470 }
4471 if( m_args.size() >= 2 )
4472 {
4473 if( m_args[1] == "xml" )
4474 listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsXml );
4475 else if( m_args[1] == "text" )
4476 listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsText );
4477 else
4478 return setErrorMode( m_command + " expected [xml] or [text] but recieved: [" + m_args[1] + "]" );
4479 }
4480 m_config.setListSpec( static_cast<Config::List::What>( m_config.getListSpec() | listSpec ) );
4481 }
4482 break;
4483 case modeTest:
4484 if( m_args.size() == 0 )
4485 return setErrorMode( m_command + " expected at least 1 argument but recieved none" );
4486 {
4487 std::vector<std::string>::const_iterator it = m_args.begin();
4488 std::vector<std::string>::const_iterator itEnd = m_args.end();
4489 for(; it != itEnd; ++it )
4490 m_config.addTestSpec( *it );
4491 }
4492 break;
4493 case modeReport:
4494 if( m_args.size() != 1 )
4495 return setErrorMode( m_command + " expected one argument, recieved: " + argsAsString() );
4496 m_config.setReporter( m_args[0] );
4497 break;
4498 case modeOutput:
4499 if( m_args.size() == 0 )
4500 return setErrorMode( m_command + " expected filename" );
4501 if( m_args[0][0] == '%' )
4502 m_config.useStream( m_args[0].substr( 1 ) );
4503 else
4504 m_config.setFilename( m_args[0] );
4505 break;
4506 case modeSuccess:
4507 if( m_args.size() != 0 )
4508 return setErrorMode( m_command + " does not accept arguments" );
4509 m_config.setIncludeWhat( Config::Include::SuccessfulResults );
4510 break;
4511 case modeBreak:
4512 if( m_args.size() != 0 )
4513 return setErrorMode( m_command + " does not accept arguments" );
4514 m_config.setShouldDebugBreak( true );
4515 break;
4516 case modeName:
4517 if( m_args.size() != 1 )
4518 return setErrorMode( m_command + " requires exactly one argument (a name)" );
4519 m_config.setName( m_args[0] );
4520 break;
4521 case modeHelp:
4522 if( m_args.size() != 0 )
4523 return setErrorMode( m_command + " does not accept arguments" );
4524 m_config.setShowHelp( true );
4525 break;
4526 default:
4527 break;
4528 }
4529 m_args.clear();
4530 m_mode = mode;
4531 }
4532
4533 ///////////////////////////////////////////////////////////////////////
4534 void setErrorMode
4535 (
4536 const std::string& errorMessage
4537 )
4538 {
4539 m_mode = modeError;
4540 m_command = "";
4541 m_config.setError( errorMessage );
4542 }
4543
4544 private:
4545
4546 Mode m_mode;
4547 std::string m_command;
4548 std::vector<std::string> m_args;
4549 Config& m_config;
4550 };
4551
4552
4553} // end namespace Catch
4554
4555// #included from: internal/catch_list.hpp
4556
4557/*
4558 * catch_list.hpp
4559 * Catch
4560 *
4561 * Created by Phil on 5/11/2010.
4562 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
4563 *
4564 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4565 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4566 *
4567 */
4568
4569#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4570
4571#include <limits>
4572
4573namespace Catch
4574{
4575 ///////////////////////////////////////////////////////////////////////////
4576 inline int List
4577 (
4578 const Config& config
4579 )
4580 {
4581 if( config.listWhat() & Config::List::Reports )
4582 {
4583 std::cout << "Available reports:\n";
4584 IReporterRegistry::FactoryMap::const_iterator it = Hub::getReporterRegistry().getFactories().begin();
4585 IReporterRegistry::FactoryMap::const_iterator itEnd = Hub::getReporterRegistry().getFactories().end();
4586 for(; it != itEnd; ++it )
4587 {
4588 // !TBD: consider listAs()
4589 std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
4590 }
4591 std::cout << std::endl;
4592 }
4593 if( config.listWhat() & Config::List::Tests )
4594 {
4595 std::cout << "Available tests:\n";
4596 std::vector<TestCaseInfo>::const_iterator it = Hub::getTestCaseRegistry().getAllTests().begin();
4597 std::vector<TestCaseInfo>::const_iterator itEnd = Hub::getTestCaseRegistry().getAllTests().end();
4598 for(; it != itEnd; ++it )
4599 {
4600 // !TBD: consider listAs()
4601 std::cout << "\t" << it->getName() << "\n\t\t '" << it->getDescription() << "'\n";
4602 }
4603 std::cout << std::endl;
4604 }
4605 if( ( config.listWhat() & Config::List::All ) == 0 )
4606 {
4607 std::cerr << "Unknown list type" << std::endl;
4608 return (std::numeric_limits<int>::max)();
4609 }
4610
4611 if( config.getReporter() )
4612 {
4613 std::cerr << "Reporters ignored when listing" << std::endl;
4614 }
4615 if( !config.testsSpecified() )
4616 {
4617 std::cerr << "Test specs ignored when listing" << std::endl;
4618 }
4619 return 0;
4620
4621 }
4622
4623} // end namespace Catch
4624
4625// #included from: reporters/catch_reporter_basic.hpp
4626
4627/*
4628 * catch_reporter_basic.hpp
4629 * Catch
4630 *
4631 * Created by Phil on 28/10/2010.
4632 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
4633 *
4634 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4635 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4636 *
4637 */
4638#define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
4639
Phil Nashf721a962011-06-07 14:13:57 +01004640// #included from: ../internal/catch_reporter_registrars.hpp
Phil Nash89d1e6c2011-05-24 08:23:02 +01004641
4642/*
4643 * catch_reporter_registrars.hpp
4644 * Test
4645 *
4646 * Created by Phil on 31/12/2010.
4647 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
4648 *
4649 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4650 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4651 *
4652 */
4653#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
4654
4655
4656namespace Catch
4657{
4658 template<typename T>
4659 class ReporterRegistrar
4660 {
4661 class ReporterFactory : public IReporterFactory
4662 {
4663 ///////////////////////////////////////////////////////////////////
4664 virtual IReporter* create
4665 (
4666 const IReporterConfig& config
4667 )
4668 const
4669 {
4670 return new T( config );
4671 }
4672 ///////////////////////////////////////////////////////////////////
4673 virtual std::string getDescription
4674 ()
4675 const
4676 {
4677 return T::getDescription();
4678 }
4679 };
4680
4681 public:
4682
4683 ///////////////////////////////////////////////////////////////////////
4684 ReporterRegistrar
4685 (
4686 const std::string& name
4687 )
4688 {
4689 Hub::getReporterRegistry().registerReporter( name, new ReporterFactory() );
4690 }
4691 };
4692}
4693
4694///////////////////////////////////////////////////////////////////////////////
4695#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
4696 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
4697
4698
4699namespace Catch
4700{
4701 class BasicReporter : public IReporter
4702 {
4703 struct SpanInfo
4704 {
4705 SpanInfo()
4706 : emitted( false )
4707 {}
4708
4709 SpanInfo( const std::string& spanName )
4710 : name( spanName ),
4711 emitted( false )
4712 {}
4713
4714 SpanInfo( const SpanInfo& other )
4715 : name( other.name ),
4716 emitted( other.emitted )
4717 {}
4718
4719 std::string name;
4720 bool emitted;
4721 };
4722
4723 public:
4724 ///////////////////////////////////////////////////////////////////////////
4725 BasicReporter
4726 (
4727 const IReporterConfig& config
4728 )
4729 : m_config( config )
4730 {
4731 }
4732
4733 ///////////////////////////////////////////////////////////////////////////
4734 static std::string getDescription
4735 ()
4736 {
4737 return "Reports test results as lines of text";
4738 }
4739
4740 private:
4741
4742 ///////////////////////////////////////////////////////////////////////////
4743 void ReportCounts
4744 (
4745 std::size_t succeeded,
4746 std::size_t failed
4747 )
4748 {
4749 if( failed + succeeded == 0 )
4750 m_config.stream() << "No tests ran";
4751 else if( failed == 0 )
4752 m_config.stream() << "All " << succeeded << " test(s) succeeded";
4753 else if( succeeded == 0 )
4754 m_config.stream() << "All " << failed << " test(s) failed";
4755 else
4756 m_config.stream() << succeeded << " test(s) passed but " << failed << " test(s) failed";
4757 }
4758
4759 private: // IReporter
4760
4761 ///////////////////////////////////////////////////////////////////////////
4762 virtual void StartTesting
4763 ()
4764 {
4765 m_testingSpan = SpanInfo();
4766 }
4767
4768 ///////////////////////////////////////////////////////////////////////////
4769 virtual void EndTesting
4770 (
4771 std::size_t succeeded,
4772 std::size_t failed
4773 )
4774 {
4775 // Output the overall test results even if "Started Testing" was not emitted
4776 m_config.stream() << "[Testing completed. ";
4777 ReportCounts( succeeded, failed );
4778 m_config.stream() << "]\n" << std::endl;
4779 }
4780
4781 ///////////////////////////////////////////////////////////////////////////
4782 virtual void StartGroup
4783 (
4784 const std::string& groupName
4785 )
4786 {
4787 m_groupSpan = groupName;
4788 }
4789
4790 ///////////////////////////////////////////////////////////////////////////
4791 virtual void EndGroup
4792 (
4793 const std::string& groupName,
4794 std::size_t succeeded,
4795 std::size_t failed
4796 )
4797 {
4798 if( m_groupSpan.emitted && !groupName.empty() )
4799 {
4800 m_config.stream() << "[End of group: '" << groupName << "'. ";
4801 ReportCounts( succeeded, failed );
4802 m_config.stream() << "]\n" << std::endl;
4803 m_groupSpan = SpanInfo();
4804 }
4805 }
4806
4807 ///////////////////////////////////////////////////////////////////////////
4808 virtual void StartTestCase
4809 (
4810 const TestCaseInfo& testInfo
4811 )
4812 {
4813 m_testSpan = testInfo.getName();
4814 }
4815
4816 ///////////////////////////////////////////////////////////////////////////
4817 virtual void StartSection
4818 (
4819 const std::string& sectionName,
4820 const std::string /*description*/
4821 )
4822 {
4823 m_sectionSpans.push_back( SpanInfo( sectionName ) );
4824 }
4825
4826 ///////////////////////////////////////////////////////////////////////////
4827 virtual void EndSection
4828 (
4829 const std::string& sectionName,
4830 std::size_t succeeded,
4831 std::size_t failed
4832 )
4833 {
4834 SpanInfo& sectionSpan = m_sectionSpans.back();
4835 if( sectionSpan.emitted && !sectionSpan.name.empty() )
4836 {
4837 m_config.stream() << "[End of section: '" << sectionName << "'. ";
4838 ReportCounts( succeeded, failed );
4839 m_config.stream() << "]\n" << std::endl;
4840 }
4841 m_sectionSpans.pop_back();
4842 }
4843
4844 ///////////////////////////////////////////////////////////////////////////
4845 virtual void Result
4846 (
4847 const ResultInfo& resultInfo
4848 )
4849 {
4850 if( !m_config.includeSuccessfulResults() && resultInfo.getResultType() == ResultWas::Ok )
4851 return;
4852
4853 StartSpansLazily();
4854
4855 if( !resultInfo.getFilename().empty() )
4856#ifndef __GNUG__
4857 m_config.stream() << resultInfo.getFilename() << "(" << resultInfo.getLine() << "): ";
4858#else
4859 m_config.stream() << resultInfo.getFilename() << ":" << resultInfo.getLine() << ": ";
4860#endif
4861
4862 if( resultInfo.hasExpression() )
4863 {
4864 m_config.stream() << resultInfo.getExpression();
4865 if( resultInfo.ok() )
4866 m_config.stream() << " succeeded";
4867 else
4868 m_config.stream() << " failed";
4869 }
4870 switch( resultInfo.getResultType() )
4871 {
4872 case ResultWas::ThrewException:
4873 if( resultInfo.hasExpression() )
4874 m_config.stream() << " with unexpected";
4875 else
4876 m_config.stream() << "Unexpected";
4877 m_config.stream() << " exception with message: '" << resultInfo.getMessage() << "'";
4878 break;
4879 case ResultWas::DidntThrowException:
4880 if( resultInfo.hasExpression() )
4881 m_config.stream() << " because no exception was thrown where one was expected";
4882 else
4883 m_config.stream() << "No exception thrown where one was expected";
4884 break;
4885 case ResultWas::Info:
4886 streamVariableLengthText( "info", resultInfo.getMessage() );
4887 break;
4888 case ResultWas::Warning:
4889 m_config.stream() << "warning:\n'" << resultInfo.getMessage() << "'";
4890 break;
4891 case ResultWas::ExplicitFailure:
4892 m_config.stream() << "failed with message: '" << resultInfo.getMessage() << "'";
4893 break;
4894 default:
4895 if( !resultInfo.hasExpression() )
4896 {
4897 if( resultInfo.ok() )
4898 m_config.stream() << " succeeded";
4899 else
4900 m_config.stream() << " failed";
4901 }
4902 break;
4903 }
4904
4905 if( resultInfo.hasExpression() )
4906 {
4907 m_config.stream() << " for: " << resultInfo.getExpandedExpression();
4908 }
4909 m_config.stream() << std::endl;
4910 }
4911
4912 ///////////////////////////////////////////////////////////////////////////
4913 virtual void EndTestCase
4914 (
4915 const TestCaseInfo& testInfo,
4916 std::size_t succeeded,
4917 std::size_t failed,
4918 const std::string& stdOut,
4919 const std::string& stdErr
4920 )
4921 {
4922 if( !stdOut.empty() )
4923 {
4924 StartSpansLazily();
4925 streamVariableLengthText( "stdout", stdOut );
4926 }
4927
4928 if( !stdErr.empty() )
4929 {
4930 StartSpansLazily();
4931 streamVariableLengthText( "stderr", stdErr );
4932 }
4933
4934 if( m_testSpan.emitted )
4935 {
4936 m_config.stream() << "[Finished: " << testInfo.getName() << " ";
4937 ReportCounts( succeeded, failed );
4938 m_config.stream() << "]" << std::endl;
4939 }
4940 }
4941
4942 private: // helpers
4943
4944 ///////////////////////////////////////////////////////////////////////////
4945 void StartSpansLazily()
4946 {
4947 if( !m_testingSpan.emitted )
4948 {
4949 if( m_config.getName().empty() )
4950 m_config.stream() << "[Started testing]" << std::endl;
4951 else
4952 m_config.stream() << "[Started testing: " << m_config.getName() << "]" << std::endl;
4953 m_testingSpan.emitted = true;
4954 }
4955
4956 if( !m_groupSpan.emitted && !m_groupSpan.name.empty() )
4957 {
4958 m_config.stream() << "[Started group: '" << m_groupSpan.name << "']" << std::endl;
4959 m_groupSpan.emitted = true;
4960 }
4961
4962 if( !m_testSpan.emitted )
4963 {
4964 m_config.stream() << std::endl << "[Running: " << m_testSpan.name << "]" << std::endl;
4965 m_testSpan.emitted = true;
4966 }
4967
4968 if( !m_sectionSpans.empty() )
4969 {
4970 SpanInfo& sectionSpan = m_sectionSpans.back();
4971 if( !sectionSpan.emitted && !sectionSpan.name.empty() )
4972 {
4973 if( m_firstSectionInTestCase )
4974 {
4975 m_config.stream() << "\n";
4976 m_firstSectionInTestCase = false;
4977 }
4978 std::vector<SpanInfo>::iterator it = m_sectionSpans.begin();
4979 std::vector<SpanInfo>::iterator itEnd = m_sectionSpans.end();
4980 for(; it != itEnd; ++it )
4981 {
4982 SpanInfo& prevSpan = *it;
4983 if( !prevSpan.emitted && !prevSpan.name.empty() )
4984 {
4985 m_config.stream() << "[Started section: '" << prevSpan.name << "']" << std::endl;
4986 prevSpan.emitted = true;
4987 }
4988 }
4989 }
4990 }
4991 }
4992
4993 ///////////////////////////////////////////////////////////////////////////
4994 void streamVariableLengthText
4995 (
4996 const std::string& prefix,
4997 const std::string& text
4998 )
4999 {
5000 std::string trimmed = trim( text );
5001 if( trimmed.find_first_of( "\r\n" ) == std::string::npos )
5002 {
5003 m_config.stream() << "[" << prefix << ": " << trimmed << "]\n";
5004 }
5005 else
5006 {
5007 m_config.stream() << "\n[" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed
5008 << "\n[end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<<\n";
5009 }
5010 }
5011
5012 private:
5013 const IReporterConfig& m_config;
5014 bool m_firstSectionInTestCase;
5015
5016 SpanInfo m_testingSpan;
5017 SpanInfo m_groupSpan;
5018 SpanInfo m_testSpan;
5019 std::vector<SpanInfo> m_sectionSpans;
5020 };
5021
5022 INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
5023
5024} // end namespace Catch
5025
5026// #included from: reporters/catch_reporter_xml.hpp
5027
5028/*
5029 * catch_reporter_xml.hpp
5030 * Catch
5031 *
5032 * Created by Phil on 28/10/2010.
5033 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
5034 *
5035 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5036 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5037 *
5038 */
5039#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
5040
Phil Nashf721a962011-06-07 14:13:57 +01005041// #included from: ../internal/catch_xmlwriter.hpp
Phil Nash89d1e6c2011-05-24 08:23:02 +01005042
5043/*
5044 * catch_xmlwriter.hpp
5045 * Catch
5046 *
5047 * Created by Phil on 09/12/2010.
5048 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
5049 *
5050 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5051 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5052 */
5053#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
5054
5055#include <sstream>
5056#include <string>
5057#include <vector>
5058
5059namespace Catch
5060{
5061 class XmlWriter
5062 {
5063 public:
5064
5065 class ScopedElement
5066 {
5067 public:
5068 ///////////////////////////////////////////////////////////////////
5069 ScopedElement
5070 (
5071 XmlWriter* writer
5072 )
5073 : m_writer( writer )
5074 {
5075 }
5076
5077 ///////////////////////////////////////////////////////////////////
5078 ScopedElement
5079 (
5080 const ScopedElement& other
5081 )
5082 : m_writer( other.m_writer )
5083 {
5084 other.m_writer = NULL;
5085 }
5086
5087 ///////////////////////////////////////////////////////////////////
5088 ~ScopedElement
5089 ()
5090 {
5091 if( m_writer )
5092 m_writer->endElement();
5093 }
5094
5095 ///////////////////////////////////////////////////////////////////
5096 ScopedElement& writeText
5097 (
5098 const std::string& text
5099 )
5100 {
5101 m_writer->writeText( text );
5102 return *this;
5103 }
5104
5105 ///////////////////////////////////////////////////////////////////
5106 template<typename T>
5107 ScopedElement& writeAttribute
5108 (
5109 const std::string& name,
5110 const T& attribute
5111 )
5112 {
5113 m_writer->writeAttribute( name, attribute );
5114 return *this;
5115 }
5116
5117 private:
5118 mutable XmlWriter* m_writer;
5119 };
5120
5121 ///////////////////////////////////////////////////////////////////////
5122 XmlWriter
5123 ()
5124 : m_tagIsOpen( false ),
5125 m_needsNewline( false ),
5126 m_os( &std::cout )
5127 {
5128 }
5129
5130 ///////////////////////////////////////////////////////////////////////
5131 XmlWriter
5132 (
5133 std::ostream& os
5134 )
5135 : m_tagIsOpen( false ),
5136 m_needsNewline( false ),
5137 m_os( &os )
5138 {
5139 }
5140
5141 ///////////////////////////////////////////////////////////////////////
5142 ~XmlWriter
5143 ()
5144 {
5145 while( !m_tags.empty() )
5146 {
5147 endElement();
5148 }
5149 }
5150
5151 ///////////////////////////////////////////////////////////////////////
5152 XmlWriter& operator =
5153 (
5154 const XmlWriter& other
5155 )
5156 {
5157 XmlWriter temp( other );
5158 swap( temp );
5159 return *this;
5160 }
5161
5162 ///////////////////////////////////////////////////////////////////////
5163 void swap
5164 (
5165 XmlWriter& other
5166 )
5167 {
5168 std::swap( m_tagIsOpen, other.m_tagIsOpen );
5169 std::swap( m_needsNewline, other.m_needsNewline );
5170 std::swap( m_tags, other.m_tags );
5171 std::swap( m_indent, other.m_indent );
5172 std::swap( m_os, other.m_os );
5173 }
5174
5175 ///////////////////////////////////////////////////////////////////////
5176 XmlWriter& startElement
5177 (
5178 const std::string& name
5179 )
5180 {
5181 ensureTagClosed();
5182 newlineIfNecessary();
5183 stream() << m_indent << "<" << name;
5184 m_tags.push_back( name );
5185 m_indent += " ";
5186 m_tagIsOpen = true;
5187 return *this;
5188 }
5189
5190 ///////////////////////////////////////////////////////////////////////
5191 ScopedElement scopedElement
5192 (
5193 const std::string& name
5194 )
5195 {
5196 ScopedElement scoped( this );
5197 startElement( name );
5198 return scoped;
5199 }
5200
5201 ///////////////////////////////////////////////////////////////////////
5202 XmlWriter& endElement
5203 ()
5204 {
5205 newlineIfNecessary();
5206 m_indent = m_indent.substr( 0, m_indent.size()-2 );
5207 if( m_tagIsOpen )
5208 {
5209 stream() << "/>\n";
5210 m_tagIsOpen = false;
5211 }
5212 else
5213 {
5214 stream() << m_indent << "</" << m_tags.back() << ">\n";
5215 }
5216 m_tags.pop_back();
5217 return *this;
5218 }
5219
5220 ///////////////////////////////////////////////////////////////////////
5221 XmlWriter& writeAttribute
5222 (
5223 const std::string& name,
5224 const std::string& attribute
5225 )
5226 {
5227 if( !name.empty() && !attribute.empty() )
5228 {
5229 stream() << " " << name << "=\"";
5230 writeEncodedText( attribute );
5231 stream() << "\"";
5232 }
5233 return *this;
5234 }
5235
5236 ///////////////////////////////////////////////////////////////////////
5237 XmlWriter& writeAttribute
5238 (
5239 const std::string& name,
5240 bool attribute
5241 )
5242 {
5243 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
5244 return *this;
5245 }
5246
5247 ///////////////////////////////////////////////////////////////////////
5248 template<typename T>
5249 XmlWriter& writeAttribute
5250 (
5251 const std::string& name,
5252 const T& attribute
5253 )
5254 {
5255 if( !name.empty() )
5256 {
5257 stream() << " " << name << "=\"" << attribute << "\"";
5258 }
5259 return *this;
5260 }
5261
5262 ///////////////////////////////////////////////////////////////////////
5263 XmlWriter& writeText
5264 (
5265 const std::string& text
5266 )
5267 {
5268 if( !text.empty() )
5269 {
5270 bool tagWasOpen = m_tagIsOpen;
5271 ensureTagClosed();
5272 if( tagWasOpen )
5273 stream() << m_indent;
5274 writeEncodedText( text );
5275 m_needsNewline = true;
5276 }
5277 return *this;
5278 }
5279
5280 ///////////////////////////////////////////////////////////////////////
5281 XmlWriter& writeComment
5282 (
5283 const std::string& text
5284 )
5285 {
5286 ensureTagClosed();
5287 stream() << m_indent << "<!--" << text << "-->";
5288 m_needsNewline = true;
5289 return *this;
5290 }
5291
5292 ///////////////////////////////////////////////////////////////////////
5293 XmlWriter& writeBlankLine
5294 ()
5295 {
5296 ensureTagClosed();
5297 stream() << "\n";
5298 return *this;
5299 }
5300
5301 private:
5302
5303 ///////////////////////////////////////////////////////////////////////
5304 std::ostream& stream
5305 ()
5306 {
5307 return *m_os;
5308 }
5309
5310 ///////////////////////////////////////////////////////////////////////
5311 void ensureTagClosed
5312 ()
5313 {
5314 if( m_tagIsOpen )
5315 {
5316 stream() << ">\n";
5317 m_tagIsOpen = false;
5318 }
5319 }
5320
5321 ///////////////////////////////////////////////////////////////////////
5322 void newlineIfNecessary
5323 ()
5324 {
5325 if( m_needsNewline )
5326 {
5327 stream() << "\n";
5328 m_needsNewline = false;
5329 }
5330 }
5331
5332 ///////////////////////////////////////////////////////////////////////
5333 void writeEncodedText
5334 (
5335 const std::string& text
5336 )
5337 {
5338 // !TBD finish this
5339 if( !findReplaceableString( text, "<", "&lt;" ) &&
5340 !findReplaceableString( text, "&", "&amp;" ) &&
5341 !findReplaceableString( text, "\"", "&quote;" ) )
5342 {
5343 stream() << text;
5344 }
5345 }
5346
5347 ///////////////////////////////////////////////////////////////////////
5348 bool findReplaceableString
5349 (
5350 const std::string& text,
5351 const std::string& replaceWhat,
5352 const std::string& replaceWith
5353 )
5354 {
5355 std::string::size_type pos = text.find_first_of( replaceWhat );
5356 if( pos != std::string::npos )
5357 {
5358 stream() << text.substr( 0, pos ) << replaceWith;
5359 writeEncodedText( text.substr( pos+1 ) );
5360 return true;
5361 }
5362 return false;
5363 }
5364
5365 bool m_tagIsOpen;
5366 bool m_needsNewline;
5367 std::vector<std::string> m_tags;
5368 std::string m_indent;
5369 std::ostream* m_os;
5370 };
5371
5372}
5373
5374namespace Catch
5375{
5376 class XmlReporter : public Catch::IReporter
5377 {
5378 public:
5379 ///////////////////////////////////////////////////////////////////////////
5380 XmlReporter
5381 (
5382 const IReporterConfig& config
5383 )
5384 : m_config( config )
5385 {
5386 }
5387
5388 ///////////////////////////////////////////////////////////////////////////
5389 static std::string getDescription
5390 ()
5391 {
5392 return "Reports test results as an XML document";
5393 }
5394
5395 private: // IReporter
5396
5397 ///////////////////////////////////////////////////////////////////////////
5398 virtual void StartTesting
5399 ()
5400 {
5401 m_xml = XmlWriter( m_config.stream() );
5402 m_xml.startElement( "Catch" );
5403 if( !m_config.getName().empty() )
5404 m_xml.writeAttribute( "name", m_config.getName() );
5405 }
5406
5407 ///////////////////////////////////////////////////////////////////////////
5408 virtual void EndTesting
5409 (
5410 std::size_t succeeded,
5411 std::size_t failed
5412 )
5413 {
5414 m_xml.scopedElement( "OverallResults" )
5415 .writeAttribute( "successes", succeeded )
5416 .writeAttribute( "failures", failed );
5417 m_xml.endElement();
5418 }
5419
5420 ///////////////////////////////////////////////////////////////////////////
5421 virtual void StartGroup
5422 (
5423 const std::string& groupName
5424 )
5425 {
5426 m_xml.startElement( "Group" )
5427 .writeAttribute( "name", groupName );
5428 }
5429
5430 ///////////////////////////////////////////////////////////////////////////
5431 virtual void EndGroup
5432 (
5433 const std::string& /*groupName*/,
5434 std::size_t succeeded,
5435 std::size_t failed
5436 )
5437 {
5438 m_xml.scopedElement( "OverallResults" )
5439 .writeAttribute( "successes", succeeded )
5440 .writeAttribute( "failures", failed );
5441 m_xml.endElement();
5442 }
5443
5444 ///////////////////////////////////////////////////////////////////////////
5445 virtual void StartSection( const std::string& sectionName, const std::string description )
5446 {
5447 m_xml.startElement( "Section" )
5448 .writeAttribute( "name", sectionName )
5449 .writeAttribute( "description", description );
5450 }
5451
5452 ///////////////////////////////////////////////////////////////////////////
5453 virtual void EndSection( const std::string& /*sectionName*/, std::size_t succeeded, std::size_t failed )
5454 {
5455 m_xml.scopedElement( "OverallResults" )
5456 .writeAttribute( "successes", succeeded )
5457 .writeAttribute( "failures", failed );
5458 m_xml.endElement();
5459 }
5460
5461 ///////////////////////////////////////////////////////////////////////////
5462 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo )
5463 {
5464 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.getName() );
5465 m_currentTestSuccess = true;
5466 }
5467
5468 ///////////////////////////////////////////////////////////////////////////
5469 virtual void Result( const Catch::ResultInfo& resultInfo )
5470 {
5471 if( !m_config.includeSuccessfulResults() && resultInfo.getResultType() == ResultWas::Ok )
5472 return;
5473
5474 if( resultInfo.hasExpression() )
5475 {
5476 m_xml.startElement( "Expression" )
5477 .writeAttribute( "success", resultInfo.ok() )
5478 .writeAttribute( "filename", resultInfo.getFilename() )
5479 .writeAttribute( "line", resultInfo.getLine() );
5480
5481 m_xml.scopedElement( "Original" )
5482 .writeText( resultInfo.getExpression() );
5483 m_xml.scopedElement( "Expanded" )
5484 .writeText( resultInfo.getExpandedExpression() );
5485 m_currentTestSuccess &= resultInfo.ok();
5486 }
5487
5488 switch( resultInfo.getResultType() )
5489 {
5490 case ResultWas::ThrewException:
5491 m_xml.scopedElement( "Exception" )
5492 .writeAttribute( "filename", resultInfo.getFilename() )
5493 .writeAttribute( "line", resultInfo.getLine() )
5494 .writeText( resultInfo.getMessage() );
5495 m_currentTestSuccess = false;
5496 break;
5497 case ResultWas::Info:
5498 m_xml.scopedElement( "Info" )
5499 .writeText( resultInfo.getMessage() );
5500 break;
5501 case ResultWas::Warning:
5502 m_xml.scopedElement( "Warning" )
5503 .writeText( resultInfo.getMessage() );
5504 break;
5505 case ResultWas::ExplicitFailure:
5506 m_xml.scopedElement( "Failure" )
5507 .writeText( resultInfo.getMessage() );
5508 m_currentTestSuccess = false;
5509 break;
5510 default:
5511 break;
5512 }
5513 if( resultInfo.hasExpression() )
5514 m_xml.endElement();
5515 }
5516
5517 ///////////////////////////////////////////////////////////////////////////
5518 virtual void EndTestCase( const Catch::TestCaseInfo&, std::size_t /* succeeded */, std::size_t /* failed */, const std::string& /*stdOut*/, const std::string& /*stdErr*/ )
5519 {
5520 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
5521 m_xml.endElement();
5522 }
5523
5524 private:
5525 const IReporterConfig& m_config;
5526 bool m_currentTestSuccess;
5527 XmlWriter m_xml;
5528 };
5529
5530 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
5531
5532} // end namespace Catch
5533
5534// #included from: reporters/catch_reporter_junit.hpp
5535
5536/*
5537 * catch_reporter_junit.hpp
5538 * Catch
5539 *
5540 * Created by Phil on 26/11/2010.
5541 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
5542 *
5543 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5544 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5545 *
5546 */
5547#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
5548
5549
5550namespace Catch
5551{
5552 class JunitReporter : public Catch::IReporter
5553 {
5554 struct TestStats
5555 {
5556 std::string m_element;
5557 std::string m_resultType;
5558 std::string m_message;
5559 std::string m_content;
5560 };
5561
5562 struct TestCaseStats
5563 {
5564 TestCaseStats( const std::string& name = std::string() )
5565 : m_name( name )
5566 {
5567 }
5568
5569 double m_timeInSeconds;
5570 std::string m_status;
5571 std::string m_className;
5572 std::string m_name;
5573 std::vector<TestStats> m_testStats;
5574 };
5575
5576 struct Stats
5577 {
5578 Stats( const std::string& name = std::string() )
5579 : m_testsCount( 0 ),
5580 m_failuresCount( 0 ),
5581 m_disabledCount( 0 ),
5582 m_errorsCount( 0 ),
5583 m_timeInSeconds( 0 ),
5584 m_name( name )
5585 {
5586 }
5587
5588 std::size_t m_testsCount;
5589 std::size_t m_failuresCount;
5590 std::size_t m_disabledCount;
5591 std::size_t m_errorsCount;
5592 double m_timeInSeconds;
5593 std::string m_name;
5594
5595 std::vector<TestCaseStats> m_testCaseStats;
5596 };
5597
5598 public:
5599 ///////////////////////////////////////////////////////////////////////////
5600 JunitReporter( const IReporterConfig& config )
5601 : m_config( config ),
5602 m_testSuiteStats( "AllTests" ),
5603 m_currentStats( &m_testSuiteStats )
5604 {
5605 }
5606
5607 ///////////////////////////////////////////////////////////////////////////
5608 static std::string getDescription()
5609 {
5610 return "Reports test results in an XML format that looks like Ant's junitreport target";
5611 }
5612
5613 private: // IReporter
5614
5615 ///////////////////////////////////////////////////////////////////////////
5616 virtual void StartTesting()
5617 {
5618 }
5619
5620 ///////////////////////////////////////////////////////////////////////////
5621 virtual void StartGroup( const std::string& groupName )
5622 {
5623
5624 m_statsForSuites.push_back( Stats( groupName ) );
5625 m_currentStats = &m_statsForSuites.back();
5626 }
5627
5628 ///////////////////////////////////////////////////////////////////////////
5629 virtual void EndGroup( const std::string&, std::size_t succeeded, std::size_t failed )
5630 {
5631 m_currentStats->m_testsCount = failed+succeeded;
5632 m_currentStats = &m_testSuiteStats;
5633 }
5634
5635 virtual void StartSection( const std::string& /*sectionName*/, const std::string /*description*/ )
5636 {
5637 }
5638
5639 virtual void EndSection( const std::string& /*sectionName*/, std::size_t /*succeeded*/, std::size_t /*failed*/ )
5640 {
5641 }
5642
5643 ///////////////////////////////////////////////////////////////////////////
5644 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo )
5645 {
5646 m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getName() ) );
5647
5648 }
5649
5650 ///////////////////////////////////////////////////////////////////////////
5651 virtual void Result( const Catch::ResultInfo& resultInfo )
5652 {
5653 if( resultInfo.getResultType() != ResultWas::Ok || m_config.includeSuccessfulResults() )
5654 {
5655 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back();
5656 TestStats stats;
5657 std::ostringstream oss;
5658 if( !resultInfo.getMessage().empty() )
5659 {
5660 oss << resultInfo.getMessage() << " at ";
5661 }
5662 oss << resultInfo.getFilename() << ":" << resultInfo.getLine();
5663 stats.m_content = oss.str();
5664 stats.m_message = resultInfo.getExpandedExpression();
5665 stats.m_resultType = resultInfo.getTestMacroName();
5666 switch( resultInfo.getResultType() )
5667 {
5668 case ResultWas::ThrewException:
5669 stats.m_element = "error";
5670 m_currentStats->m_errorsCount++;
5671 break;
5672 case ResultWas::Info:
5673 stats.m_element = "info"; // !TBD ?
5674 break;
5675 case ResultWas::Warning:
5676 stats.m_element = "warning"; // !TBD ?
5677 break;
5678 case ResultWas::ExplicitFailure:
5679 stats.m_element = "failure";
5680 m_currentStats->m_failuresCount++;
5681 break;
5682 case ResultWas::ExpressionFailed:
5683 stats.m_element = "failure";
5684 m_currentStats->m_failuresCount++;
5685 break;
5686 case ResultWas::Ok:
5687 stats.m_element = "success";
5688 break;
5689 default:
5690 stats.m_element = "unknown";
5691 break;
5692 }
5693 testCaseStats.m_testStats.push_back( stats );
5694
5695 }
5696 }
5697
5698 ///////////////////////////////////////////////////////////////////////////
5699 virtual void EndTestCase( const Catch::TestCaseInfo&, std::size_t /* succeeded */, std::size_t /* failed */, const std::string& stdOut, const std::string& stdErr )
5700 {
5701 if( !stdOut.empty() )
5702 m_stdOut << stdOut << "\n";
5703 if( !stdErr.empty() )
5704 m_stdErr << stdErr << "\n";
5705 }
5706
5707 ///////////////////////////////////////////////////////////////////////////
5708 virtual void EndTesting( std::size_t /* succeeded */, std::size_t /* failed */ )
5709 {
5710 std::ostream& str = m_config.stream();
5711 {
5712 XmlWriter xml( str );
5713
5714 if( m_statsForSuites.size() > 0 )
5715 xml.startElement( "testsuites" );
5716
5717 std::vector<Stats>::const_iterator it = m_statsForSuites.begin();
5718 std::vector<Stats>::const_iterator itEnd = m_statsForSuites.end();
5719
5720 for(; it != itEnd; ++it )
5721 {
5722 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
5723 xml.writeAttribute( "name", it->m_name );
5724 xml.writeAttribute( "errors", it->m_errorsCount );
5725 xml.writeAttribute( "failures", it->m_failuresCount );
5726 xml.writeAttribute( "tests", it->m_testsCount );
5727 xml.writeAttribute( "hostname", "tbd" );
5728 xml.writeAttribute( "time", "tbd" );
5729 xml.writeAttribute( "timestamp", "tbd" );
5730
5731 OutputTestCases( xml, *it );
5732 }
5733
5734 xml.scopedElement( "system-out" ).writeText( trim( m_stdOut.str() ) );
5735 xml.scopedElement( "system-err" ).writeText( trim( m_stdOut.str() ) );
5736 }
5737 }
5738
5739 ///////////////////////////////////////////////////////////////////////////
5740 void OutputTestCases( XmlWriter& xml, const Stats& stats )
5741 {
5742 std::vector<TestCaseStats>::const_iterator it = stats.m_testCaseStats.begin();
5743 std::vector<TestCaseStats>::const_iterator itEnd = stats.m_testCaseStats.end();
5744 for(; it != itEnd; ++it )
5745 {
5746 xml.writeBlankLine();
5747 xml.writeComment( "Test case" );
5748
5749 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
5750 xml.writeAttribute( "classname", it->m_className );
5751 xml.writeAttribute( "name", it->m_name );
5752 xml.writeAttribute( "time", "tbd" );
5753
5754 OutputTestResult( xml, *it );
5755 }
5756 }
5757
5758
5759 ///////////////////////////////////////////////////////////////////////////
5760 void OutputTestResult( XmlWriter& xml, const TestCaseStats& stats )
5761 {
5762 std::vector<TestStats>::const_iterator it = stats.m_testStats.begin();
5763 std::vector<TestStats>::const_iterator itEnd = stats.m_testStats.end();
5764 for(; it != itEnd; ++it )
5765 {
5766 if( it->m_element != "success" )
5767 {
5768 XmlWriter::ScopedElement e = xml.scopedElement( it->m_element );
5769
5770 xml.writeAttribute( "message", it->m_message );
5771 xml.writeAttribute( "type", it->m_resultType );
5772 if( !it->m_content.empty() )
5773 xml.writeText( it->m_content );
5774 }
5775 }
5776 }
5777
5778 private:
5779 const IReporterConfig& m_config;
5780 bool m_currentTestSuccess;
5781
5782 Stats m_testSuiteStats;
5783 Stats* m_currentStats;
5784 std::vector<Stats> m_statsForSuites;
5785 std::ostringstream m_stdOut;
5786 std::ostringstream m_stdErr;
5787 };
5788
5789 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
5790
5791} // end namespace Catch
5792
5793
5794#include <fstream>
5795#include <stdlib.h>
5796#include <limits>
5797
5798namespace Catch
5799{
5800 //////////////////////////////////////////////////////////////////////////
5801 inline int Main
5802 (
5803 Config& config
5804 )
5805 {
5806 // Handle list request
5807 if( config.listWhat() != Config::List::None )
5808 return List( config );
5809
5810 // Open output file, if specified
5811 std::ofstream ofs;
5812 if( !config.getFilename().empty() )
5813 {
5814 ofs.open( config.getFilename().c_str() );
5815 if( ofs.fail() )
5816 {
5817 std::cerr << "Unable to open file: '" << config.getFilename() << "'" << std::endl;
5818 return (std::numeric_limits<int>::max)();
5819 }
5820 config.setStreamBuf( ofs.rdbuf() );
5821 }
5822
5823 Runner runner( config );
5824
5825 // Run test specs specified on the command line - or default to all
5826 if( !config.testsSpecified() )
5827 {
5828 config.getReporter()->StartGroup( "" );
5829 runner.runAll();
5830 config.getReporter()->EndGroup( "", runner.getSuccessCount(), runner.getFailureCount() );
5831 }
5832 else
5833 {
5834 // !TBD We should get all the testcases upfront, report any missing,
5835 // then just run them
5836 std::vector<std::string>::const_iterator it = config.getTestSpecs().begin();
5837 std::vector<std::string>::const_iterator itEnd = config.getTestSpecs().end();
5838 for(; it != itEnd; ++it )
5839 {
5840 size_t prevSuccess = runner.getSuccessCount();
5841 size_t prevFail = runner.getFailureCount();
5842 config.getReporter()->StartGroup( *it );
5843 if( runner.runMatching( *it ) == 0 )
5844 {
5845 // Use reporter?
5846// std::cerr << "\n[Unable to match any test cases with: " << *it << "]" << std::endl;
5847 }
5848 config.getReporter()->EndGroup( *it, runner.getSuccessCount()-prevSuccess, runner.getFailureCount()-prevFail );
5849 }
5850 }
5851 return static_cast<int>( runner.getFailureCount() );
5852 }
5853
5854 //////////////////////////////////////////////////////////////////////////
5855 void showHelp
5856 (
5857 std::string exeName
5858 )
5859 {
5860 std::string::size_type pos = exeName.find_last_of( "/\\" );
5861 if( pos != std::string::npos )
5862 {
5863 exeName = exeName.substr( pos+1 );
5864 }
5865
5866 std::cout << exeName << " is a CATCH host application. Options are as follows:\n\n"
5867 << "\t-l, --list <tests | reporters> [xml]\n"
5868 << "\t-t, --test <testspec> [<testspec>...]\n"
5869 << "\t-r, --reporter <reporter name>\n"
5870 << "\t-o, --out <file name>|<%stream name>\n"
5871 << "\t-s, --success\n"
5872 << "\t-b, --break\n"
5873 << "\t-n, --name <name>\n\n"
5874 << "For more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line" << std::endl;
5875 }
5876
5877 //////////////////////////////////////////////////////////////////////////
5878 inline int Main
5879 (
5880 int argc,
5881 char* const argv[],
5882 Config& config
5883 )
5884 {
5885 ArgParser( argc, argv, config );
5886
5887 if( !config.getMessage().empty() )
5888 {
5889 std::cerr << config.getMessage() << std::endl;
5890 return (std::numeric_limits<int>::max)();
5891 }
5892
5893 // Handle help
5894 if( config.showHelp() )
5895 {
5896 showHelp( argv[0] );
5897 return 0;
5898 }
5899
5900 return Main( config );
5901 }
5902
5903 //////////////////////////////////////////////////////////////////////////
5904 inline int Main
5905 (
5906 int argc,
5907 char* const argv[]
5908 )
5909 {
5910 Config config;
5911// if( isDebuggerActive() )
5912// config.useStream( "debug" );
5913 return Main( argc, argv, config );
5914 }
5915
5916} // end namespace Catch
5917
5918#endif
5919
5920#ifdef CATCH_CONFIG_MAIN
5921// #included from: internal/catch_default_main.hpp
5922
5923/*
5924 * catch_default_main.hpp
5925 * Catch
5926 *
5927 * Created by Phil on 20/05/2011.
5928 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
5929 *
5930 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5931 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5932 *
5933 */
5934
5935#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
5936
5937int main (int argc, char * const argv[])
5938{
5939#ifdef __OBJC__
5940
5941 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
5942
5943 Catch::registerTestMethods();
5944
5945 int result = Catch::Main( argc, (char* const*)argv );
5946
5947 [pool drain];
5948 return result;
5949
5950#else
5951
5952 return Catch::Main( argc, argv );
5953
5954#endif
5955}
5956
5957
5958#endif
5959
5960#ifdef __OBJC__
5961// #included from: internal/catch_objc.hpp
5962
5963/*
5964 * catch_objc.hpp
5965 * Catch
5966 *
5967 * Created by Phil on 14/11/2010.
5968 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
5969 *
5970 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5971 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5972 *
5973 */
5974
5975#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
5976
5977#import <objc/runtime.h>
5978#include <string>
5979
Phil Nash6b6143c2011-05-31 07:51:04 +01005980// NB. Any general catch headers included here must be included
5981// in catch.hpp first to make sure they are included by the single
5982// header for non obj-usage
Phil Nash89d1e6c2011-05-24 08:23:02 +01005983
5984///////////////////////////////////////////////////////////////////////////////
5985// This protocol is really only here for (self) documenting purposes, since
5986// all its methods are optional.
5987@protocol OcFixture
5988
5989@optional
5990
5991-(void) setUp;
5992-(void) tearDown;
5993
5994@end
5995
5996namespace Catch
5997{
5998 class OcMethod : public ITestCase
5999 {
6000 public:
6001 ///////////////////////////////////////////////////////////////////////
6002 OcMethod
6003 (
6004 Class cls,
6005 SEL sel
6006 )
6007 : m_cls( cls ),
6008 m_sel( sel )
6009 {
6010 }
6011
6012 ///////////////////////////////////////////////////////////////////////
6013 virtual void invoke
6014 ()
6015 const
6016 {
6017 id obj = class_createInstance( m_cls, 0 );
6018 obj = [obj init];
6019
6020 if( [obj respondsToSelector: @selector(setUp) ] )
6021 [obj performSelector: @selector(setUp)];
6022
6023 if( [obj respondsToSelector: m_sel] )
6024 [obj performSelector: m_sel];
6025
6026 if( [obj respondsToSelector: @selector(tearDown) ] )
6027 [obj performSelector: @selector(tearDown)];
6028
6029 [obj release];
6030 }
6031
6032 ///////////////////////////////////////////////////////////////////////
6033 virtual ITestCase* clone
6034 ()
6035 const
6036 {
6037 return new OcMethod( m_cls, m_sel );
6038 }
6039
6040 ///////////////////////////////////////////////////////////////////////
6041 virtual bool operator ==
6042 (
6043 const ITestCase& other
6044 )
6045 const
6046 {
6047 const OcMethod* ocmOther = dynamic_cast<const OcMethod*> ( &other );
6048 return ocmOther && ocmOther->m_sel == m_sel;
6049 }
6050
6051 ///////////////////////////////////////////////////////////////////////
6052 virtual bool operator <
6053 (
6054 const ITestCase& other
6055 )
6056 const
6057 {
6058 const OcMethod* ocmOther = dynamic_cast<const OcMethod*> ( &other );
6059 return ocmOther && ocmOther->m_sel < m_sel;
6060 }
6061
6062 private:
6063 Class m_cls;
6064 SEL m_sel;
6065 };
6066
6067 namespace Detail
6068 {
6069
6070 ///////////////////////////////////////////////////////////////////////
6071 inline bool startsWith
6072 (
6073 const std::string& str,
6074 const std::string& sub
6075 )
6076 {
6077 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
6078 }
6079
6080 ///////////////////////////////////////////////////////////////////////
6081 inline const char* getAnnotation
6082 (
6083 Class cls,
6084 const std::string& annotationName,
6085 const std::string& testCaseName
6086 )
6087 {
6088 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
6089 SEL sel = NSSelectorFromString( selStr );
6090 [selStr release];
6091 if( [cls respondsToSelector: sel] )
6092 return (const char*)[cls performSelector: sel];
6093 return "";
6094 }
6095 }
6096
6097 ///////////////////////////////////////////////////////////////////////////
6098 inline size_t registerTestMethods
6099 ()
6100 {
6101 size_t noTestMethods = 0;
6102 int noClasses = objc_getClassList( NULL, 0 );
6103
6104 std::vector<Class> classes( noClasses );
6105 objc_getClassList( &classes[0], noClasses );
6106
6107 for( int c = 0; c < noClasses; c++ )
6108 {
6109 Class cls = classes[c];
6110 {
6111 u_int count;
6112 Method* methods = class_copyMethodList( cls, &count );
6113 for( int m = 0; m < count ; m++ )
6114 {
6115 SEL selector = method_getName(methods[m]);
6116 std::string methodName = sel_getName(selector);
6117 if( Detail::startsWith( methodName, "Catch_TestCase_" ) )
6118 {
6119 std::string testCaseName = methodName.substr( 15 );
6120 const char* name = Detail::getAnnotation( cls, "Name", testCaseName );
6121 const char* desc = Detail::getAnnotation( cls, "Description", testCaseName );
6122
6123 Hub::getTestCaseRegistry().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name, desc, "", 0 ) );
6124 noTestMethods++;
6125
6126 }
6127 }
6128 free(methods);
6129 }
6130 }
6131 return noTestMethods;
6132 }
6133}
6134
6135///////////////////////////////////////////////////////////////////////////////
6136#define OC_TEST_CASE( name, desc )\
6137+(const char*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
6138{\
6139return name; \
6140}\
6141+(const char*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
6142{ \
6143return desc; \
6144} \
6145-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
6146
6147#endif
6148
6149//////
6150
6151#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "REQUIRE" )
6152#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "REQUIRE_FALSE" )
6153
6154#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "REQUIRE_THROWS" )
6155#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "REQUIRE_THROWS_AS" )
6156#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "REQUIRE_NOTHROW" )
6157
6158#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CHECK" )
6159#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CHECK_FALSE" )
6160
6161#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CHECK_THROWS" )
6162#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" )
6163#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CHECK_NOTHROW" )
6164
6165#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" )
6166#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" )
6167#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
6168#define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
6169#define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CAPTURE" )
6170
6171#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
6172
6173#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
6174#define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
6175#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
6176#define METHOD_AS_TEST_CASE( method, name, description ) CATCH_METHOD_AS_TEST_CASE( method, name, description )
6177
6178#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
6179#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
6180
6181#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
6182
6183///////////////
6184// Still to be implemented
6185#define CHECK_NOFAIL( expr ) // !TBD - reports violation, but doesn't fail Test
6186
6187using Catch::Detail::Approx;
6188
6189#endif // TWOBLUECUBES_CATCH_HPP_INCLUDED
6190