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