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