blob: 88a0e5bfbaa49349f27cfea4601b2da105d306a2 [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 Nash333e6e62012-02-17 19:50:59 +00001959 try \
1960 { \
1961 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr, isNot )->*expr ), stopOnFailure ); \
1962 if( Catch::isTrue( false ) ){ bool internal_catch_dummyResult = ( expr ); Catch::isTrue( internal_catch_dummyResult ); } \
1963 } \
1964 catch( Catch::TestFailureException& ) \
1965 { \
1966 throw; \
1967 } \
1968 catch( ... ) \
1969 { \
1970 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false ); \
1971 throw; \
1972 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001973
1974///////////////////////////////////////////////////////////////////////////////
Phil Nasha162e222012-02-10 08:30:13 +00001975#define INTERNAL_CATCH_IF( expr, isNot, stopOnFailure, macroName ) \
1976 INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \
1977 if( Catch::Hub::getResultCapture().getLastResult()->ok() )
1978
1979///////////////////////////////////////////////////////////////////////////////
1980#define INTERNAL_CATCH_ELSE( expr, isNot, stopOnFailure, macroName ) \
1981 INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \
1982 if( !Catch::Hub::getResultCapture().getLastResult()->ok() )
1983
1984///////////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01001985#define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \
1986 try \
1987 { \
1988 expr; \
1989 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure ); \
1990 } \
Phil Nash89d1e6c2011-05-24 08:23:02 +01001991 catch( ... ) \
1992 { \
1993 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \
1994 }
1995
1996///////////////////////////////////////////////////////////////////////////////
1997#define INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
1998 try \
1999 { \
2000 expr; \
2001 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure ); \
2002 } \
2003 catch( Catch::TestFailureException& ) \
2004 { \
2005 throw; \
2006 } \
2007 catch( exceptionType ) \
2008 { \
2009 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure ); \
2010 }
2011
2012///////////////////////////////////////////////////////////////////////////////
2013#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, stopOnFailure, macroName ) \
2014 INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
2015 catch( ... ) \
2016 { \
2017 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr ) << Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure ); \
2018 }
2019
2020///////////////////////////////////////////////////////////////////////////////
2021#define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \
2022 Catch::Hub::getResultCapture().acceptExpression( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName ) << reason ).setResultType( resultType ) );
2023
2024///////////////////////////////////////////////////////////////////////////////
2025#define INTERNAL_CATCH_SCOPED_INFO( log ) \
2026 Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
2027 INTERNAL_CATCH_UNIQUE_NAME( info ) << log
2028
2029// #included from: internal/catch_section.hpp
2030
2031/*
2032 * catch_section.hpp
2033 * Catch
2034 *
2035 * Created by Phil on 03/11/2010.
2036 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2037 *
2038 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2039 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2040 *
2041 */
2042
2043#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
2044
2045
2046#include <string>
2047
2048namespace Catch
2049{
2050 class Section
2051 {
2052 public:
2053 ///////////////////////////////////////////////////////////////////////
2054 Section
2055 (
2056 const std::string& name,
2057 const std::string& description,
2058 const std::string& filename,
2059 std::size_t line
2060 )
2061 : m_name( name ),
Phil Nashf7299fc2012-02-25 09:39:45 +00002062 m_sectionIncluded( Hub::getResultCapture().sectionStarted( name, description, filename, line, m_assertions ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002063 {
2064 }
2065
2066 ///////////////////////////////////////////////////////////////////////
2067 ~Section
2068 ()
2069 {
2070 if( m_sectionIncluded )
Phil Nashf7299fc2012-02-25 09:39:45 +00002071 Hub::getResultCapture().sectionEnded( m_name, m_assertions );
Phil Nash89d1e6c2011-05-24 08:23:02 +01002072 }
2073
2074 ///////////////////////////////////////////////////////////////////////
2075 // This indicates whether the section should be executed or not
2076 operator bool
2077 ()
2078 {
2079 return m_sectionIncluded;
2080 }
2081
2082 private:
2083
2084 std::string m_name;
Phil Nashf7299fc2012-02-25 09:39:45 +00002085 Counts m_assertions;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002086 bool m_sectionIncluded;
2087 };
2088
2089} // end namespace Catch
2090
2091#define INTERNAL_CATCH_SECTION( name, desc ) \
2092 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, __FILE__, __LINE__ ) )
2093
2094// #included from: internal/catch_generators.hpp
2095
2096/*
2097 * catch_generators.hpp
2098 * Catch
2099 *
2100 * Created by Phil on 27/01/2011.
2101 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
2102 *
2103 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2104 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2105 *
2106 */
2107
2108#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2109
2110
2111#include <iterator>
2112#include <vector>
2113#include <string>
2114#include <stdlib.h>
2115
2116namespace Catch
2117{
2118
2119template<typename T>
2120struct IGenerator
2121{
2122 virtual ~IGenerator
2123 ()
2124 {}
2125
2126 virtual T getValue
2127 ( std::size_t index
2128 ) const = 0;
2129
2130 virtual std::size_t size
2131 () const = 0;
2132};
2133
2134template<typename T>
2135class BetweenGenerator : public IGenerator<T>
2136{
2137public:
2138 ///////////////////////////////////////////////////////////////////////////
2139 BetweenGenerator
2140 (
2141 T from,
2142 T to
2143 )
2144 : m_from( from ),
2145 m_to( to )
2146 {
2147 }
2148
2149 ///////////////////////////////////////////////////////////////////////////
2150 virtual T getValue
2151 (
2152 std::size_t index
2153 )
2154 const
2155 {
2156 return m_from+static_cast<T>( index );
2157 }
2158
2159 ///////////////////////////////////////////////////////////////////////////
2160 virtual std::size_t size
2161 ()
2162 const
2163 {
2164 return 1+m_to-m_from;
2165 }
2166
2167private:
2168
2169 T m_from;
2170 T m_to;
2171};
2172
2173template<typename T>
2174class ValuesGenerator : public IGenerator<T>
2175{
2176public:
2177 ///////////////////////////////////////////////////////////////////////////
2178 ValuesGenerator
2179 ()
2180 {
2181 }
2182
2183 ///////////////////////////////////////////////////////////////////////////
2184 void add
2185 (
2186 T value
2187 )
2188 {
2189 m_values.push_back( value );
2190 }
2191
2192 ///////////////////////////////////////////////////////////////////////////
2193 virtual T getValue
2194 (
2195 std::size_t index
2196 )
2197 const
2198 {
2199 return m_values[index];
2200 }
2201
2202 ///////////////////////////////////////////////////////////////////////////
2203 virtual std::size_t size
2204 ()
2205 const
2206 {
2207 return m_values.size();
2208 }
2209
2210private:
2211
2212 std::vector<T> m_values;
2213};
2214
2215template<typename T>
2216class CompositeGenerator
2217{
2218public:
2219 ///////////////////////////////////////////////////////////////////////////
2220 CompositeGenerator()
2221 : m_totalSize( 0 )
2222 {
2223 }
2224
2225 ///////////////////////////////////////////////////////////////////////////
2226 // *** Move semantics, similar to auto_ptr ***
2227 CompositeGenerator( CompositeGenerator& other )
2228 : m_fileInfo( other.m_fileInfo ),
2229 m_totalSize( 0 )
2230 {
2231 move( other );
2232 }
2233
2234 ///////////////////////////////////////////////////////////////////////////
2235 CompositeGenerator& setFileInfo
2236 (
2237 const char* fileInfo
2238 )
2239 {
2240 m_fileInfo = fileInfo;
2241 return *this;
2242 }
2243
2244 ///////////////////////////////////////////////////////////////////////////
2245 ~CompositeGenerator
2246 ()
2247 {
2248 deleteAll( m_composed );
2249 }
2250
2251 ///////////////////////////////////////////////////////////////////////////
2252 operator T
2253 ()
2254 const
2255 {
2256 size_t overallIndex = Hub::getGeneratorIndex( m_fileInfo, m_totalSize );
2257
2258 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2259 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2260 for( size_t index = 0; it != itEnd; ++it )
2261 {
2262 const IGenerator<T>* generator = *it;
2263 if( overallIndex >= index && overallIndex < index + generator->size() )
2264 {
2265 return generator->getValue( overallIndex-index );
2266 }
2267 index += generator->size();
2268 }
2269 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
2270 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
2271 }
2272
2273 ///////////////////////////////////////////////////////////////////////////
2274 void add
2275 (
2276 const IGenerator<T>* generator
2277 )
2278 {
2279 m_totalSize += generator->size();
2280 m_composed.push_back( generator );
2281 }
2282
2283 ///////////////////////////////////////////////////////////////////////////
2284 CompositeGenerator& then
2285 (
2286 CompositeGenerator& other
2287 )
2288 {
2289 move( other );
2290 return *this;
2291 }
2292
2293 ///////////////////////////////////////////////////////////////////////////
2294 CompositeGenerator& then
2295 (
2296 T value
2297 )
2298 {
2299 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2300 valuesGen->add( value );
2301 add( valuesGen );
2302 return *this;
2303 }
2304
2305private:
2306
2307 ///////////////////////////////////////////////////////////////////////////
2308 void move
2309 (
2310 CompositeGenerator& other
2311 )
2312 {
2313 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
2314 m_totalSize += other.m_totalSize;
2315 other.m_composed.clear();
2316 }
2317
2318 std::vector<const IGenerator<T>*> m_composed;
2319 std::string m_fileInfo;
2320 size_t m_totalSize;
2321};
2322
2323namespace Generators
2324{
2325 ///////////////////////////////////////////////////////////////////////////
2326 template<typename T>
2327 CompositeGenerator<T> between
2328 (
2329 T from,
2330 T to
2331 )
2332 {
2333 CompositeGenerator<T> generators;
2334 generators.add( new BetweenGenerator<T>( from, to ) );
2335 return generators;
2336 }
2337
2338 ///////////////////////////////////////////////////////////////////////////
2339 template<typename T>
2340 CompositeGenerator<T> values
2341 (
2342 T val1,
2343 T val2
2344 )
2345 {
2346 CompositeGenerator<T> generators;
2347 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2348 valuesGen->add( val1 );
2349 valuesGen->add( val2 );
2350 generators.add( valuesGen );
2351 return generators;
2352 }
2353
2354 ///////////////////////////////////////////////////////////////////////////
2355 template<typename T>
2356 CompositeGenerator<T> values
2357 (
2358 T val1,
2359 T val2,
2360 T val3
2361 )
2362 {
2363 CompositeGenerator<T> generators;
2364 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2365 valuesGen->add( val1 );
2366 valuesGen->add( val2 );
2367 valuesGen->add( val3 );
2368 generators.add( valuesGen );
2369 return generators;
2370 }
2371
2372 ///////////////////////////////////////////////////////////////////////////
2373 template<typename T>
2374 CompositeGenerator<T> values
2375 (
2376 T val1,
2377 T val2,
2378 T val3,
2379 T val4
2380 )
2381 {
2382 CompositeGenerator<T> generators;
2383 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2384 valuesGen->add( val1 );
2385 valuesGen->add( val2 );
2386 valuesGen->add( val3 );
2387 valuesGen->add( val4 );
2388 generators.add( valuesGen );
2389 return generators;
2390 }
2391
2392} // end namespace Generators
2393
2394using namespace Generators;
2395
2396} // end namespace Catch
2397
2398#define INTERNAL_CATCH_LINESTR2( line ) #line
2399#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2400
2401#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2402
2403// #included from: internal/catch_interfaces_exception.h
2404
2405/*
2406 * catch_exception_interfaces.h
2407 * Catch
2408 *
2409 * Created by Phil on 20/04/2011.
2410 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
2411 *
2412 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2413 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2414 *
2415 */
2416#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTIONS_H_INCLUDED
2417
2418#include <string>
2419
2420namespace Catch
2421{
2422 typedef std::string(*exceptionTranslateFunction)();
2423
2424 struct IExceptionTranslator
2425 {
2426 virtual ~IExceptionTranslator(){}
2427 virtual std::string translate() const = 0;
2428 };
2429
2430 struct IExceptionTranslatorRegistry
2431 {
2432 virtual ~IExceptionTranslatorRegistry
2433 ()
2434 {}
2435
2436 virtual void registerTranslator
2437 ( IExceptionTranslator* translator
2438 ) = 0;
2439 virtual std::string translateActiveException
2440 () const = 0;
2441
2442 };
2443
2444 class ExceptionTranslatorRegistrar
2445 {
2446 template<typename T>
2447 class ExceptionTranslator : public IExceptionTranslator
2448 {
2449 public:
2450
2451 ExceptionTranslator
2452 (
2453 std::string(*translateFunction)( T& )
2454 )
2455 : m_translateFunction( translateFunction )
2456 {}
2457
2458 virtual std::string translate
2459 ()
2460 const
2461 {
2462 try
2463 {
2464 throw;
2465 }
2466 catch( T& ex )
2467 {
2468 return m_translateFunction( ex );
2469 }
2470 }
2471
2472 protected:
2473 std::string(*m_translateFunction)( T& );
2474 };
2475
2476 public:
2477 template<typename T>
2478 ExceptionTranslatorRegistrar
2479 (
2480 std::string(*translateFunction)( T& )
2481 )
2482 {
2483 Catch::Hub::getExceptionTranslatorRegistry().registerTranslator
2484 ( new ExceptionTranslator<T>( translateFunction ) );
2485 }
2486 };
2487}
2488
2489///////////////////////////////////////////////////////////////////////////////
2490#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2491 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2492 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2493 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2494
2495// #included from: internal/catch_approx.hpp
2496
2497/*
2498 * catch_approx.hpp
2499 * Catch
2500 *
2501 * Created by Phil on 28/04/2011.
2502 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2503 *
2504 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2505 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2506 *
2507 */
2508#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2509
2510
2511#include <cmath>
2512#include <limits>
2513
2514namespace Catch
2515{
2516 namespace Detail
2517 {
2518 class Approx
2519 {
2520 public:
2521 ///////////////////////////////////////////////////////////////////////////
2522 explicit Approx
2523 (
Phil Nashf721a962011-06-07 14:13:57 +01002524 double value
Phil Nash89d1e6c2011-05-24 08:23:02 +01002525 )
Phil Nashf721a962011-06-07 14:13:57 +01002526 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
Phil Nash89d1e6c2011-05-24 08:23:02 +01002527 m_scale( 1.0 ),
Phil Nashf721a962011-06-07 14:13:57 +01002528 m_value( value )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002529 {
2530 }
2531
2532 ///////////////////////////////////////////////////////////////////////////
Phil Nashf721a962011-06-07 14:13:57 +01002533 Approx
2534 (
2535 const Approx& other
2536 )
2537 : m_epsilon( other.m_epsilon ),
2538 m_scale( other.m_scale ),
2539 m_value( other.m_value )
2540 {
2541 }
2542
2543 ///////////////////////////////////////////////////////////////////////////
2544 static Approx custom
2545 ()
2546 {
2547 return Approx( 0 );
2548 }
2549
2550 ///////////////////////////////////////////////////////////////////////////
2551 Approx operator()
2552 (
2553 double value
2554 )
2555 {
2556 Approx approx( value );
2557 approx.epsilon( m_epsilon );
2558 approx.scale( m_scale );
2559 return approx;
2560 }
2561
2562 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002563 friend bool operator ==
2564 (
Phil Nash6b6143c2011-05-31 07:51:04 +01002565 double lhs,
Phil Nash89d1e6c2011-05-24 08:23:02 +01002566 const Approx& rhs
2567 )
2568 {
2569 // Thanks to Richard Harris for his help refining this formula
Phil Nashf721a962011-06-07 14:13:57 +01002570 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 +01002571 }
2572
2573 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002574 friend bool operator ==
2575 (
2576 const Approx& lhs,
Phil Nash6b6143c2011-05-31 07:51:04 +01002577 double rhs
Phil Nash89d1e6c2011-05-24 08:23:02 +01002578 )
2579 {
2580 return operator==( rhs, lhs );
2581 }
2582
2583 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002584 friend bool operator !=
2585 (
Phil Nash6b6143c2011-05-31 07:51:04 +01002586 double lhs,
Phil Nash89d1e6c2011-05-24 08:23:02 +01002587 const Approx& rhs
2588 )
2589 {
2590 return !operator==( lhs, rhs );
2591 }
2592
2593 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01002594 friend bool operator !=
2595 (
2596 const Approx& lhs,
Phil Nash6b6143c2011-05-31 07:51:04 +01002597 double rhs
Phil Nash89d1e6c2011-05-24 08:23:02 +01002598 )
2599 {
2600 return !operator==( rhs, lhs );
2601 }
2602
2603
2604 ///////////////////////////////////////////////////////////////////////////
2605 Approx& epsilon
2606 (
2607 double newEpsilon
2608 )
2609 {
2610 m_epsilon = newEpsilon;
2611 return *this;
2612 }
2613
2614 ///////////////////////////////////////////////////////////////////////////
2615 Approx& scale
2616 (
2617 double newScale
2618 )
2619 {
2620 m_scale = newScale;
2621 return *this;
2622 }
2623
2624 ///////////////////////////////////////////////////////////////////////////
2625 std::string toString() const
2626 {
2627 std::ostringstream oss;
Phil Nashf721a962011-06-07 14:13:57 +01002628 oss << "Approx( " << m_value << ")";
Phil Nash89d1e6c2011-05-24 08:23:02 +01002629 return oss.str();
2630 }
2631
2632 private:
2633 double m_epsilon;
2634 double m_scale;
Phil Nashf721a962011-06-07 14:13:57 +01002635 double m_value;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002636 };
2637 }
2638
2639 ///////////////////////////////////////////////////////////////////////////////
2640 template<>
2641 inline std::string toString<Detail::Approx>
2642 (
2643 const Detail::Approx& value
2644 )
2645 {
2646 return value.toString();
2647 }
2648
2649} // end namespace Catch
2650
Phil Nash83224e62011-08-12 18:53:28 +01002651// #included from: internal/catch_test_case_info.hpp
Phil Nash89d1e6c2011-05-24 08:23:02 +01002652
2653/*
2654 * catch_test_case_info.hpp
2655 * Catch
2656 *
2657 * Created by Phil on 29/10/2010.
2658 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2659 *
2660 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2661 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2662 *
2663 */
2664
2665#define TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED
2666
2667#include <map>
2668#include <string>
2669
2670namespace Catch
2671{
2672 class TestCaseInfo
2673 {
2674 public:
2675 ///////////////////////////////////////////////////////////////////////
2676 TestCaseInfo
2677 (
2678 ITestCase* testCase,
2679 const char* name,
2680 const char* description,
2681 const char* filename,
2682 std::size_t line
2683 )
2684 : m_test( testCase ),
2685 m_name( name ),
2686 m_description( description ),
2687 m_filename( filename ),
2688 m_line( line )
2689 {
2690 }
2691
2692 ///////////////////////////////////////////////////////////////////////
2693 TestCaseInfo
2694 ()
Phil Nashf51d3162011-12-28 10:37:31 +00002695 : m_test( NULL ),
2696 m_name(),
2697 m_description(),
2698 m_filename(),
2699 m_line( 0 )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002700 {
2701 }
2702
2703 ///////////////////////////////////////////////////////////////////////
2704 TestCaseInfo
2705 (
2706 const TestCaseInfo& other
2707 )
2708 : m_test( other.m_test->clone() ),
2709 m_name( other.m_name ),
2710 m_description( other.m_description ),
2711 m_filename( other.m_filename ),
2712 m_line( other.m_line )
2713 {
2714 }
2715
2716 ///////////////////////////////////////////////////////////////////////
2717 TestCaseInfo
2718 (
2719 const TestCaseInfo& other,
2720 const std::string& name
2721 )
2722 : m_test( other.m_test->clone() ),
2723 m_name( name ),
2724 m_description( other.m_description ),
2725 m_filename( other.m_filename ),
2726 m_line( other.m_line )
2727 {
2728 }
2729
2730 ///////////////////////////////////////////////////////////////////////
2731 TestCaseInfo& operator =
2732 (
2733 const TestCaseInfo& other
2734 )
2735 {
2736 TestCaseInfo temp( other );
2737 swap( temp );
2738 return *this;
2739 }
2740
2741 ///////////////////////////////////////////////////////////////////////
2742 ~TestCaseInfo
2743 ()
2744 {
2745 delete m_test;
2746 }
2747
2748 ///////////////////////////////////////////////////////////////////////
2749 void invoke
2750 ()
2751 const
2752 {
2753 m_test->invoke();
2754 }
2755
2756 ///////////////////////////////////////////////////////////////////////
2757 const std::string& getName
2758 ()
2759 const
2760 {
2761 return m_name;
2762 }
2763
2764 ///////////////////////////////////////////////////////////////////////
2765 const std::string& getDescription
2766 ()
2767 const
2768 {
2769 return m_description;
2770 }
2771
2772 ///////////////////////////////////////////////////////////////////////
2773 const std::string& getFilename
2774 ()
2775 const
2776 {
2777 return m_filename;
2778 }
2779
2780 ///////////////////////////////////////////////////////////////////////
2781 std::size_t getLine
2782 ()
2783 const
2784 {
2785 return m_line;
2786 }
2787
2788 ///////////////////////////////////////////////////////////////////////
2789 bool isHidden
2790 ()
2791 const
2792 {
2793 return m_name.size() >= 2 && m_name[0] == '.' && m_name[1] == '/';
2794 }
2795
2796 ///////////////////////////////////////////////////////////////////////
2797 void swap
2798 (
2799 TestCaseInfo& other
2800 )
2801 {
2802 std::swap( m_test, other.m_test );
2803 m_name.swap( other.m_name );
2804 m_description.swap( other.m_description );
2805 }
2806
2807 ///////////////////////////////////////////////////////////////////////
2808 bool operator ==
2809 (
2810 const TestCaseInfo& other
2811 )
2812 const
2813 {
Phil Nash4a0a70a2012-02-09 08:37:02 +00002814 return *m_test == *other.m_test && m_name == other.m_name;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002815 }
2816
2817 ///////////////////////////////////////////////////////////////////////
2818 bool operator <
2819 (
2820 const TestCaseInfo& other
2821 )
2822 const
2823 {
Phil Nash4a0a70a2012-02-09 08:37:02 +00002824 return m_name < other.m_name;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002825 }
2826
2827 private:
2828 ITestCase* m_test;
2829 std::string m_name;
2830 std::string m_description;
2831 std::string m_filename;
2832 std::size_t m_line;
2833
2834 };
2835
2836 ///////////////////////////////////////////////////////////////////////////
2837 ///////////////////////////////////////////////////////////////////////////
2838
2839 class TestSpec
2840 {
2841 public:
2842 ///////////////////////////////////////////////////////////////////////
2843 TestSpec
2844 (
2845 const std::string& rawSpec
2846 )
2847 : m_rawSpec( rawSpec ),
2848 m_isWildcarded( false )
2849 {
2850 if( m_rawSpec[m_rawSpec.size()-1] == '*' )
2851 {
2852 m_rawSpec = m_rawSpec.substr( 0, m_rawSpec.size()-1 );
2853 m_isWildcarded = true;
2854 }
2855 }
2856
2857 ///////////////////////////////////////////////////////////////////////
2858 bool matches
2859 (
2860 const std::string& testName
2861 )
2862 const
2863 {
2864 if( !m_isWildcarded )
2865 return m_rawSpec == testName;
2866 else
2867 return testName.size() >= m_rawSpec.size() && testName.substr( 0, m_rawSpec.size() ) == m_rawSpec;
2868 }
2869
2870 private:
2871 std::string m_rawSpec;
2872 bool m_isWildcarded;
2873 };
2874}
2875
2876
Phil Nash81528252011-08-15 09:06:31 +01002877#ifdef __OBJC__
2878// #included from: internal/catch_objc.hpp
2879
2880/*
2881 * catch_objc.hpp
2882 * Catch
2883 *
2884 * Created by Phil on 14/11/2010.
2885 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
2886 *
2887 * Distributed under the Boost Software License, Version 1.0. (See accompanying
2888 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
2889 *
2890 */
2891
2892#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2893
Phil Nasha162e222012-02-10 08:30:13 +00002894#import <Foundation/Foundation.h>
Phil Nash81528252011-08-15 09:06:31 +01002895#import <objc/runtime.h>
Phil Nasha162e222012-02-10 08:30:13 +00002896
Phil Nash81528252011-08-15 09:06:31 +01002897#include <string>
2898
2899// NB. Any general catch headers included here must be included
2900// in catch.hpp first to make sure they are included by the single
2901// header for non obj-usage
2902
Phil Nash83224e62011-08-12 18:53:28 +01002903///////////////////////////////////////////////////////////////////////////////
2904// This protocol is really only here for (self) documenting purposes, since
2905// all its methods are optional.
2906@protocol OcFixture
2907
2908@optional
2909
2910-(void) setUp;
2911-(void) tearDown;
2912
2913@end
2914
2915namespace Catch
2916{
2917 class OcMethod : public ITestCase
2918 {
2919 public:
2920 ///////////////////////////////////////////////////////////////////////
2921 OcMethod
2922 (
2923 Class cls,
2924 SEL sel
2925 )
2926 : m_cls( cls ),
2927 m_sel( sel )
2928 {
2929 }
2930
2931 ///////////////////////////////////////////////////////////////////////
2932 virtual void invoke
2933 ()
2934 const
2935 {
2936 id obj = class_createInstance( m_cls, 0 );
2937 obj = [obj init];
2938
2939 if( [obj respondsToSelector: @selector(setUp) ] )
2940 [obj performSelector: @selector(setUp)];
2941
2942 if( [obj respondsToSelector: m_sel] )
2943 [obj performSelector: m_sel];
2944
2945 if( [obj respondsToSelector: @selector(tearDown) ] )
2946 [obj performSelector: @selector(tearDown)];
2947
2948 [obj release];
2949 }
2950
2951 ///////////////////////////////////////////////////////////////////////
2952 virtual ITestCase* clone
2953 ()
2954 const
2955 {
2956 return new OcMethod( m_cls, m_sel );
2957 }
2958
2959 ///////////////////////////////////////////////////////////////////////
2960 virtual bool operator ==
2961 (
2962 const ITestCase& other
2963 )
2964 const
2965 {
2966 const OcMethod* ocmOther = dynamic_cast<const OcMethod*> ( &other );
2967 return ocmOther && ocmOther->m_sel == m_sel;
2968 }
2969
2970 ///////////////////////////////////////////////////////////////////////
2971 virtual bool operator <
2972 (
2973 const ITestCase& other
2974 )
2975 const
2976 {
2977 const OcMethod* ocmOther = dynamic_cast<const OcMethod*> ( &other );
2978 return ocmOther && ocmOther->m_sel < m_sel;
2979 }
2980
2981 private:
2982 Class m_cls;
2983 SEL m_sel;
2984 };
2985
2986 namespace Detail
2987 {
2988
2989 ///////////////////////////////////////////////////////////////////////
2990 inline bool startsWith
2991 (
2992 const std::string& str,
2993 const std::string& sub
2994 )
2995 {
2996 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
2997 }
2998
2999 ///////////////////////////////////////////////////////////////////////
3000 inline const char* getAnnotation
3001 (
3002 Class cls,
3003 const std::string& annotationName,
3004 const std::string& testCaseName
3005 )
3006 {
3007 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
3008 SEL sel = NSSelectorFromString( selStr );
3009 [selStr release];
3010 if( [cls respondsToSelector: sel] )
3011 return (const char*)[cls performSelector: sel];
3012 return "";
3013 }
3014 }
3015
3016 ///////////////////////////////////////////////////////////////////////////
3017 inline size_t registerTestMethods
3018 ()
3019 {
3020 size_t noTestMethods = 0;
3021 int noClasses = objc_getClassList( NULL, 0 );
3022
3023 std::vector<Class> classes( noClasses );
3024 objc_getClassList( &classes[0], noClasses );
3025
3026 for( int c = 0; c < noClasses; c++ )
3027 {
3028 Class cls = classes[c];
3029 {
3030 u_int count;
3031 Method* methods = class_copyMethodList( cls, &count );
3032 for( int m = 0; m < count ; m++ )
3033 {
3034 SEL selector = method_getName(methods[m]);
3035 std::string methodName = sel_getName(selector);
3036 if( Detail::startsWith( methodName, "Catch_TestCase_" ) )
3037 {
3038 std::string testCaseName = methodName.substr( 15 );
3039 const char* name = Detail::getAnnotation( cls, "Name", testCaseName );
3040 const char* desc = Detail::getAnnotation( cls, "Description", testCaseName );
3041
3042 Hub::getTestCaseRegistry().registerTest( TestCaseInfo( new OcMethod( cls, selector ), name, desc, "", 0 ) );
3043 noTestMethods++;
3044
3045 }
3046 }
3047 free(methods);
3048 }
3049 }
3050 return noTestMethods;
3051 }
3052}
3053
3054///////////////////////////////////////////////////////////////////////////////
3055#define OC_TEST_CASE( name, desc )\
3056+(const char*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
3057{\
3058return name; \
3059}\
3060+(const char*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
3061{ \
3062return desc; \
3063} \
3064-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3065
3066#endif
3067
3068#if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
3069// #included from: catch_runner.hpp
3070
3071/*
3072 * catch_runner.hpp
3073 * Catch
3074 *
3075 * Created by Phil on 31/10/2010.
3076 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
3077 *
3078 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3079 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3080 *
3081 */
3082
3083#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
3084
3085// #included from: internal/catch_hub_impl.hpp
3086
3087/*
3088 * catch_hub_impl.hpp
3089 * Catch
3090 *
3091 * Created by Phil on 31/12/2010.
3092 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
3093 *
3094 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3095 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3096 *
3097 */
3098// #included from: catch_reporter_registry.hpp
3099
3100/*
3101 * catch_reporter_registry.hpp
3102 * Catch
3103 *
3104 * Created by Phil on 29/10/2010.
3105 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
3106 *
3107 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3108 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3109 *
3110 */
3111#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
3112
3113
3114#include <map>
3115
3116namespace Catch
3117{
3118 class ReporterRegistry : public IReporterRegistry
3119 {
3120 public:
3121
3122 ///////////////////////////////////////////////////////////////////////
3123 ~ReporterRegistry
3124 ()
3125 {
3126 deleteAllValues( m_factories );
3127 }
3128
3129 ///////////////////////////////////////////////////////////////////////
3130 virtual IReporter* create
3131 (
3132 const std::string& name,
3133 const IReporterConfig& config
3134 )
3135 const
3136 {
3137 FactoryMap::const_iterator it = m_factories.find( name );
3138 if( it == m_factories.end() )
3139 return NULL;
3140 return it->second->create( config );
3141 }
3142
3143 ///////////////////////////////////////////////////////////////////////
3144 void registerReporter
3145 (
3146 const std::string& name,
3147 IReporterFactory* factory
3148 )
3149 {
3150 m_factories.insert( std::make_pair( name, factory ) );
3151 }
3152
3153 ///////////////////////////////////////////////////////////////////////
3154 const FactoryMap& getFactories
3155 ()
3156 const
3157 {
3158 return m_factories;
3159 }
3160
3161 private:
3162 FactoryMap m_factories;
3163 };
3164}
3165
3166// #included from: catch_test_case_registry_impl.hpp
3167
3168/*
3169 * catch_test_case_registry_impl.hpp
3170 * Catch
3171 *
3172 * Created by Phil on 7/1/2011
3173 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
3174 *
3175 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3176 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3177 *
3178 */
3179
3180
Phil Nash89d1e6c2011-05-24 08:23:02 +01003181#include <vector>
3182#include <set>
3183#include <sstream>
3184
3185#include <iostream> // !TBD DBG
3186namespace Catch
3187{
3188 class TestRegistry : public ITestCaseRegistry
3189 {
3190 public:
3191 ///////////////////////////////////////////////////////////////////////////
3192 TestRegistry
3193 ()
3194 : m_unnamedCount( 0 )
3195 {
3196 }
3197
3198 ///////////////////////////////////////////////////////////////////////////
3199 virtual void registerTest
3200 (
3201 const TestCaseInfo& testInfo
3202 )
3203 {
3204 if( testInfo.getName() == "" )
3205 {
3206 std::ostringstream oss;
3207 oss << testInfo.getName() << "unnamed/" << ++m_unnamedCount;
3208 return registerTest( TestCaseInfo( testInfo, oss.str() ) );
3209 }
3210 if( m_functions.find( testInfo ) == m_functions.end() )
3211 {
3212 m_functions.insert( testInfo );
3213 m_functionsInOrder.push_back( testInfo );
3214 }
Phil Nash4a0a70a2012-02-09 08:37:02 +00003215 else
3216 {
3217 const TestCaseInfo& prev = *m_functions.find( testInfo );
3218 std::cerr << "error: TEST_CASE( \"" << testInfo.getName() << "\" ) already defined.\n"
Phil Nash6e0f58d2012-02-15 18:37:21 +00003219 << "\tFirst seen at " << SourceLineInfo( prev.getFilename(), prev.getLine() ) << "\n"
3220 << "\tRedefined at " << SourceLineInfo( testInfo.getFilename(), testInfo.getLine() ) << std::endl;
Phil Nash4a0a70a2012-02-09 08:37:02 +00003221 exit(1);
3222 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003223 }
3224
3225 ///////////////////////////////////////////////////////////////////////////
3226 virtual const std::vector<TestCaseInfo>& getAllTests
3227 ()
3228 const
3229 {
3230 return m_functionsInOrder;
3231 }
3232
3233 ///////////////////////////////////////////////////////////////////////////
3234 virtual std::vector<TestCaseInfo> getMatchingTestCases
3235 (
3236 const std::string& rawTestSpec
3237 )
3238 {
3239 TestSpec testSpec( rawTestSpec );
3240
3241 std::vector<TestCaseInfo> testList;
3242 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
3243 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
3244 for(; it != itEnd; ++it )
3245 {
3246 if( testSpec.matches( it->getName() ) )
3247 {
3248 testList.push_back( *it );
Phil Nash89d1e6c2011-05-24 08:23:02 +01003249 }
3250 }
3251 return testList;
3252 }
3253
3254 private:
3255
3256 std::set<TestCaseInfo> m_functions;
3257 std::vector<TestCaseInfo> m_functionsInOrder;
3258 size_t m_unnamedCount;
3259 };
3260
3261 ///////////////////////////////////////////////////////////////////////////
3262 ///////////////////////////////////////////////////////////////////////////
3263
3264
3265 struct FreeFunctionTestCase : ITestCase
3266 {
3267 ///////////////////////////////////////////////////////////////////////////
3268 FreeFunctionTestCase
3269 (
3270 TestFunction fun
3271 )
3272 : m_fun( fun )
3273 {}
3274
3275 ///////////////////////////////////////////////////////////////////////////
3276 virtual void invoke
3277 ()
3278 const
3279 {
3280 m_fun();
3281 }
3282
3283 ///////////////////////////////////////////////////////////////////////////
3284 virtual ITestCase* clone
3285 ()
3286 const
3287 {
3288 return new FreeFunctionTestCase( m_fun );
3289 }
3290
3291 ///////////////////////////////////////////////////////////////////////////
3292 virtual bool operator ==
3293 (
3294 const ITestCase& other
3295 )
3296 const
3297 {
3298 const FreeFunctionTestCase* ffOther = dynamic_cast<const FreeFunctionTestCase*> ( &other );
3299 return ffOther && m_fun == ffOther->m_fun;
3300 }
3301
3302 ///////////////////////////////////////////////////////////////////////////
3303 virtual bool operator <
3304 (
3305 const ITestCase& other
3306 )
3307 const
3308 {
3309 const FreeFunctionTestCase* ffOther = dynamic_cast<const FreeFunctionTestCase*> ( &other );
3310 return ffOther && m_fun < ffOther->m_fun;
3311 }
3312
3313 private:
3314 TestFunction m_fun;
3315 };
3316
3317 ///////////////////////////////////////////////////////////////////////////
3318 ///////////////////////////////////////////////////////////////////////////
3319
3320 ///////////////////////////////////////////////////////////////////////////
3321 AutoReg::AutoReg
3322 (
3323 TestFunction function,
3324 const char* name,
3325 const char* description,
3326 const char* filename,
3327 std::size_t line
3328 )
3329 {
3330 registerTestCase( new FreeFunctionTestCase( function ), name, description, filename, line );
3331 }
3332
3333 ///////////////////////////////////////////////////////////////////////////
3334 AutoReg::~AutoReg
3335 ()
3336 {
3337 }
3338
3339 ///////////////////////////////////////////////////////////////////////////
3340 void AutoReg::registerTestCase
3341 (
3342 ITestCase* testCase,
3343 const char* name,
3344 const char* description,
3345 const char* filename,
3346 std::size_t line
3347 )
3348 {
3349 Hub::getTestCaseRegistry().registerTest( TestCaseInfo( testCase, name, description, filename, line ) );
3350 }
3351
3352} // end namespace Catch
3353
3354// #included from: catch_exception_translator_registry.hpp
3355
3356/*
3357 * catch_exception_translator_registry.hpp
3358 * Catch
3359 *
3360 * Created by Phil on 20/04/2011.
3361 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
3362 *
3363 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3364 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3365 *
3366 */
3367#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_HPP_INCLUDED
3368
3369
3370namespace Catch
3371{
3372 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry
3373 {
3374 ///////////////////////////////////////////////////////////////////////
Phil Nash3619cb22012-02-18 19:16:30 +00003375 ~ExceptionTranslatorRegistry
3376 ()
3377 {
3378 deleteAll( m_translators );
3379 }
3380
3381 ///////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01003382 virtual void registerTranslator
3383 (
3384 IExceptionTranslator* translator
3385 )
3386 {
3387 m_translators.push_back( translator );
3388 }
3389
3390 ///////////////////////////////////////////////////////////////////////
3391 virtual std::string translateActiveException
3392 ()
3393 const
3394 {
Phil Nash333e6e62012-02-17 19:50:59 +00003395 try
3396 {
3397 throw;
3398 }
3399 catch( std::exception& ex )
3400 {
3401 return ex.what();
3402 }
3403 catch( std::string& msg )
3404 {
3405 return msg;
3406 }
3407 catch( const char* msg )
3408 {
3409 return msg;
3410 }
3411 catch(...)
3412 {
3413 return tryTranslators( m_translators.begin() );
3414 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003415 }
3416
3417 ///////////////////////////////////////////////////////////////////////
3418 std::string tryTranslators
3419 (
3420 std::vector<IExceptionTranslator*>::const_iterator it
3421 )
3422 const
3423 {
3424 if( it == m_translators.end() )
3425 return "Unknown exception";
3426
3427 try
3428 {
3429 return (*it)->translate();
3430 }
3431 catch(...)
3432 {
3433 return tryTranslators( it+1 );
3434 }
3435 }
3436
3437 private:
3438 std::vector<IExceptionTranslator*> m_translators;
3439 };
3440}
3441
3442// #included from: catch_runner_impl.hpp
3443
Phil Nashf51d3162011-12-28 10:37:31 +00003444 /*
Phil Nash89d1e6c2011-05-24 08:23:02 +01003445 * catch_runner.hpp
3446 * Catch
3447 *
3448 * Created by Phil on 22/10/2010.
3449 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
3450 *
3451 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3452 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3453 *
3454 */
3455#define TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED
3456
3457// #included from: catch_interfaces_runner.h
3458
3459/*
3460 * catch_interfaces_runner.h
3461 * Catch
3462 *
3463 * Created by Phil on 07/01/2011.
3464 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
3465 *
3466 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3467 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3468 *
3469 */
3470#define TWOBLUECUBES_INTERNAL_CATCH_INTERFACES_RUNNER_H_INCLUDED
3471
Phil Nashf7299fc2012-02-25 09:39:45 +00003472
Phil Nash89d1e6c2011-05-24 08:23:02 +01003473#include <string>
3474
3475namespace Catch
3476{
3477 class TestCaseInfo;
3478
3479 struct IRunner
3480 {
3481 virtual ~IRunner
3482 ()
3483 {}
3484
3485 virtual void runAll
3486 ( bool runHiddenTests = false
3487 ) = 0;
3488
3489 virtual std::size_t runMatching
3490 ( const std::string& rawTestSpec
3491 ) = 0;
3492
Phil Nashf7299fc2012-02-25 09:39:45 +00003493 virtual Totals getTotals
Phil Nash89d1e6c2011-05-24 08:23:02 +01003494 () const = 0;
3495
3496 };
3497}
3498
3499// #included from: catch_config.hpp
3500
3501/*
3502 * catch_config.hpp
3503 * Catch
3504 *
3505 * Created by Phil on 08/11/2010.
3506 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
3507 *
3508 * Distributed under the Boost Software License, Version 1.0. (See accompanying
3509 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
3510 *
3511 */
3512
3513#define TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
3514
3515
3516#include <memory>
3517#include <vector>
3518#include <string>
3519#include <iostream>
3520
3521namespace Catch
3522{
3523
3524 class Config : public IReporterConfig
3525 {
3526 private:
3527 Config( const Config& other );
3528 Config& operator = ( const Config& other );
3529 public:
3530
3531 struct Include { enum What
3532 {
3533 FailedOnly,
3534 SuccessfulResults
3535 }; };
3536
3537 struct List{ enum What
3538 {
3539 None = 0,
3540
3541 Reports = 1,
3542 Tests = 2,
3543 All = 3,
3544
3545 WhatMask = 0xf,
3546
3547 AsText = 0x10,
3548 AsXml = 0x11,
3549
3550 AsMask = 0xf0
3551 }; };
3552
3553
3554 ///////////////////////////////////////////////////////////////////////////
3555 Config()
3556 : m_reporter( NULL ),
3557 m_listSpec( List::None ),
3558 m_shouldDebugBreak( false ),
3559 m_showHelp( false ),
Phil Nash48112c22011-05-31 18:47:30 +01003560 m_streambuf( NULL ),
3561 m_os( std::cout.rdbuf() ),
Phil Nash89d1e6c2011-05-24 08:23:02 +01003562 m_includeWhat( Include::FailedOnly )
3563 {}
3564
3565 ///////////////////////////////////////////////////////////////////////////
3566 ~Config()
3567 {
Phil Nash48112c22011-05-31 18:47:30 +01003568 m_os.rdbuf( std::cout.rdbuf() );
3569 delete m_streambuf;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003570 }
3571
3572 ///////////////////////////////////////////////////////////////////////////
3573 void setReporter( const std::string& reporterName )
3574 {
3575 if( m_reporter.get() )
3576 return setError( "Only one reporter may be specified" );
3577 setReporter( Hub::getReporterRegistry().create( reporterName, *this ) );
3578 }
3579
3580 ///////////////////////////////////////////////////////////////////////////
3581 void addTestSpec( const std::string& testSpec )
3582 {
3583 m_testSpecs.push_back( testSpec );
3584 }
3585
3586 ///////////////////////////////////////////////////////////////////////////
3587 bool testsSpecified() const
3588 {
3589 return !m_testSpecs.empty();
3590 }
3591
3592 ///////////////////////////////////////////////////////////////////////////
3593 const std::vector<std::string>& getTestSpecs() const
3594 {
3595 return m_testSpecs;
3596 }
3597
3598 ///////////////////////////////////////////////////////////////////////////
3599 List::What getListSpec( void ) const
3600 {
3601 return m_listSpec;
3602 }
3603
3604 ///////////////////////////////////////////////////////////////////////////
3605 void setListSpec( List::What listSpec )
3606 {
3607 m_listSpec = listSpec;
3608 }
3609
3610 ///////////////////////////////////////////////////////////////////////////
3611 void setFilename( const std::string& filename )
3612 {
3613 m_filename = filename;
3614 }
3615
3616 ///////////////////////////////////////////////////////////////////////////
3617 const std::string& getFilename() const
3618 {
3619 return m_filename;
3620 }
3621
3622 ///////////////////////////////////////////////////////////////////////////
3623 const std::string& getMessage() const
3624 {
3625 return m_message;
3626 }
3627
3628 ///////////////////////////////////////////////////////////////////////////
3629 void setError( const std::string& errorMessage )
3630 {
3631 m_message = errorMessage + "\n\n" + "Usage: ...";
3632 }
3633
3634 ///////////////////////////////////////////////////////////////////////////
3635 void setReporter( IReporter* reporter )
3636 {
3637 m_reporter = std::auto_ptr<IReporter>( reporter );
3638 }
3639
3640 ///////////////////////////////////////////////////////////////////////////
3641 IReporter* getReporter() const
3642 {
3643 if( !m_reporter.get() )
3644 const_cast<Config*>( this )->setReporter( Hub::getReporterRegistry().create( "basic", *this ) );
3645 return m_reporter.get();
3646 }
3647
3648 ///////////////////////////////////////////////////////////////////////////
3649 List::What listWhat() const
3650 {
3651 return static_cast<List::What>( m_listSpec & List::WhatMask );
3652 }
3653
3654 ///////////////////////////////////////////////////////////////////////////
3655 List::What listAs() const
3656 {
3657 return static_cast<List::What>( m_listSpec & List::AsMask );
3658 }
3659
3660 ///////////////////////////////////////////////////////////////////////////
3661 void setIncludeWhat( Include::What includeWhat )
3662 {
3663 m_includeWhat = includeWhat;
3664 }
3665
3666 ///////////////////////////////////////////////////////////////////////////
3667 void setShouldDebugBreak( bool shouldDebugBreakFlag )
3668 {
3669 m_shouldDebugBreak = shouldDebugBreakFlag;
3670 }
3671
3672 ///////////////////////////////////////////////////////////////////////////
3673 void setName( const std::string& name )
3674 {
3675 m_name = name;
3676 }
3677
3678 ///////////////////////////////////////////////////////////////////////////
3679 std::string getName() const
3680 {
3681 return m_name;
3682 }
3683
3684 ///////////////////////////////////////////////////////////////////////////
3685 bool shouldDebugBreak() const
3686 {
3687 return m_shouldDebugBreak;
3688 }
3689
3690 ///////////////////////////////////////////////////////////////////////////
3691 void setShowHelp( bool showHelpFlag )
3692 {
3693 m_showHelp = showHelpFlag;
3694 }
3695
3696 ///////////////////////////////////////////////////////////////////////////
3697 bool showHelp() const
3698 {
3699 return m_showHelp;
3700 }
3701
3702 ///////////////////////////////////////////////////////////////////////////
3703 virtual std::ostream& stream() const
3704 {
3705 return m_os;
3706 }
3707
3708 ///////////////////////////////////////////////////////////////////////////
3709 void setStreamBuf( std::streambuf* buf )
3710 {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003711 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
3712 }
3713
3714 ///////////////////////////////////////////////////////////////////////////
3715 void useStream( const std::string& streamName )
3716 {
Phil Nash48112c22011-05-31 18:47:30 +01003717 std::streambuf* newBuf = Hub::createStreamBuf( streamName );
3718 setStreamBuf( newBuf );
3719 delete m_streambuf;
3720 m_streambuf = newBuf;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003721 }
3722
3723 ///////////////////////////////////////////////////////////////////////////
3724 virtual bool includeSuccessfulResults() const
3725 {
3726 return m_includeWhat == Include::SuccessfulResults;
3727 }
3728
3729 private:
3730 std::auto_ptr<IReporter> m_reporter;
3731 std::string m_filename;
3732 std::string m_message;
3733 List::What m_listSpec;
3734 std::vector<std::string> m_testSpecs;
3735 bool m_shouldDebugBreak;
3736 bool m_showHelp;
3737 std::streambuf* m_streambuf;
3738 mutable std::ostream m_os;
3739 Include::What m_includeWhat;
3740 std::string m_name;
3741
3742 };
3743
3744} // end namespace Catch
3745
3746
3747#include <set>
3748#include <string>
3749
3750namespace Catch
3751{
3752
3753 class StreamRedirect
3754 {
3755 public:
3756 ///////////////////////////////////////////////////////////////////////
3757 StreamRedirect
3758 (
3759 std::ostream& stream,
3760 std::string& targetString
3761 )
3762 : m_stream( stream ),
3763 m_prevBuf( stream.rdbuf() ),
3764 m_targetString( targetString )
3765 {
3766 stream.rdbuf( m_oss.rdbuf() );
3767 }
3768
3769 ///////////////////////////////////////////////////////////////////////
3770 ~StreamRedirect
3771 ()
3772 {
Phil Nashf51d3162011-12-28 10:37:31 +00003773 m_targetString += m_oss.str();
Phil Nash89d1e6c2011-05-24 08:23:02 +01003774 m_stream.rdbuf( m_prevBuf );
3775 }
3776
3777 private:
3778 std::ostream& m_stream;
3779 std::streambuf* m_prevBuf;
3780 std::ostringstream m_oss;
3781 std::string& m_targetString;
3782 };
3783
3784
3785 ///////////////////////////////////////////////////////////////////////////
3786 ///////////////////////////////////////////////////////////////////////////
3787 class SectionInfo
3788 {
3789 public:
3790 enum Status
3791 {
3792 Root,
3793 Unknown,
3794 NonLeaf,
Phil Nash89d1e6c2011-05-24 08:23:02 +01003795 TestedLeaf
3796 };
3797
3798 ///////////////////////////////////////////////////////////////////////
3799 SectionInfo
3800 (
3801 SectionInfo* parent
3802 )
3803 : m_status( Unknown ),
3804 m_parent( parent )
3805 {
3806 }
3807
3808 ///////////////////////////////////////////////////////////////////////
3809 SectionInfo
3810 ()
3811 : m_status( Root ),
3812 m_parent( NULL )
3813 {
3814 }
3815
3816 ///////////////////////////////////////////////////////////////////////
3817 ~SectionInfo
3818 ()
3819 {
3820 deleteAllValues( m_subSections );
3821 }
3822
3823 ///////////////////////////////////////////////////////////////////////
3824 bool shouldRun
3825 ()
3826 const
3827 {
3828 return m_status != TestedLeaf;
3829 }
3830
3831 ///////////////////////////////////////////////////////////////////////
3832 bool ran
3833 ()
3834 {
3835 if( m_status != NonLeaf )
3836 {
3837 m_status = TestedLeaf;
3838 return true;
3839 }
3840 return false;
3841 }
3842
3843 ///////////////////////////////////////////////////////////////////////
Phil Nash3c20a752011-06-23 08:23:33 +01003844 SectionInfo* findSubSection
Phil Nash89d1e6c2011-05-24 08:23:02 +01003845 (
3846 const std::string& name
3847 )
3848 {
3849 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.find( name );
Phil Nash3c20a752011-06-23 08:23:33 +01003850 return it != m_subSections.end()
3851 ? it->second
3852 : NULL;
3853 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003854
Phil Nash3c20a752011-06-23 08:23:33 +01003855 ///////////////////////////////////////////////////////////////////////
3856 SectionInfo* addSubSection
3857 (
3858 const std::string& name
3859 )
3860 {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003861 SectionInfo* subSection = new SectionInfo( this );
3862 m_subSections.insert( std::make_pair( name, subSection ) );
3863 m_status = NonLeaf;
3864 return subSection;
3865 }
3866
3867 ///////////////////////////////////////////////////////////////////////
3868 SectionInfo* getParent
3869 ()
3870 {
3871 return m_parent;
3872 }
3873
3874 ///////////////////////////////////////////////////////////////////////
3875 bool hasUntestedSections
3876 ()
3877 const
3878 {
Phil Nash3c20a752011-06-23 08:23:33 +01003879 if( m_status == Unknown )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003880 return true;
3881
3882 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.begin();
3883 std::map<std::string, SectionInfo*>::const_iterator itEnd = m_subSections.end();
3884 for(; it != itEnd; ++it )
3885 {
3886 if( it->second->hasUntestedSections() )
3887 return true;
3888 }
3889 return false;
3890 }
3891
3892 private:
3893 Status m_status;
3894 std::map<std::string, SectionInfo*> m_subSections;
3895 SectionInfo* m_parent;
3896 };
3897
3898 ///////////////////////////////////////////////////////////////////////////
3899 ///////////////////////////////////////////////////////////////////////////
3900
3901 class RunningTest
3902 {
3903 enum RunStatus
3904 {
3905 NothingRun,
3906 EncounteredASection,
3907 RanAtLeastOneSection,
3908 RanToCompletionWithSections,
3909 RanToCompletionWithNoSections
3910 };
3911
3912 public:
3913 ///////////////////////////////////////////////////////////////////////
3914 explicit RunningTest
3915 (
3916 const TestCaseInfo* info = NULL
3917 )
3918 : m_info( info ),
3919 m_runStatus( RanAtLeastOneSection ),
Phil Nash3c20a752011-06-23 08:23:33 +01003920 m_currentSection( &m_rootSection ),
3921 m_changed( false )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003922 {
3923 }
3924
3925 ///////////////////////////////////////////////////////////////////////
3926 bool wasSectionSeen
3927 ()
3928 const
3929 {
3930 return m_runStatus == RanAtLeastOneSection ||
3931 m_runStatus == RanToCompletionWithSections;
3932 }
3933
3934 ///////////////////////////////////////////////////////////////////////
3935 void reset
3936 ()
3937 {
3938 m_runStatus = NothingRun;
Phil Nash3c20a752011-06-23 08:23:33 +01003939 m_changed = false;
Phil Nash89d1e6c2011-05-24 08:23:02 +01003940 }
3941
3942 ///////////////////////////////////////////////////////////////////////
3943 void ranToCompletion
3944 ()
3945 {
3946 m_runStatus = m_runStatus == RanAtLeastOneSection ||
3947 m_runStatus == EncounteredASection
3948 ? RanToCompletionWithSections
3949 : RanToCompletionWithNoSections;
3950 }
3951
3952 ///////////////////////////////////////////////////////////////////////
3953 bool addSection
3954 (
3955 const std::string& name
3956 )
3957 {
3958 if( m_runStatus == NothingRun )
3959 m_runStatus = EncounteredASection;
3960
Phil Nash3c20a752011-06-23 08:23:33 +01003961 SectionInfo* thisSection = m_currentSection->findSubSection( name );
3962 if( !thisSection )
3963 {
3964 thisSection = m_currentSection->addSubSection( name );
3965 m_changed = true;
3966 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003967
3968 if( !wasSectionSeen() && thisSection->shouldRun() )
3969 {
3970 m_currentSection = thisSection;
3971 return true;
3972 }
3973 return false;
3974 }
3975
3976 ///////////////////////////////////////////////////////////////////////
3977 void endSection
3978 (
3979 const std::string&
3980 )
3981 {
3982 if( m_currentSection->ran() )
Phil Nash3c20a752011-06-23 08:23:33 +01003983 {
Phil Nash89d1e6c2011-05-24 08:23:02 +01003984 m_runStatus = RanAtLeastOneSection;
Phil Nash3c20a752011-06-23 08:23:33 +01003985 m_changed = true;
3986 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01003987 m_currentSection = m_currentSection->getParent();
3988 }
3989
3990 ///////////////////////////////////////////////////////////////////////
3991 const TestCaseInfo& getTestCaseInfo
3992 ()
3993 const
3994 {
3995 return *m_info;
3996 }
3997
3998 ///////////////////////////////////////////////////////////////////////
3999 bool hasUntestedSections
4000 ()
4001 const
4002 {
Phil Nash3c20a752011-06-23 08:23:33 +01004003 return m_runStatus == RanAtLeastOneSection ||
4004 ( m_rootSection.hasUntestedSections() && m_changed );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004005 }
4006
4007 private:
4008 const TestCaseInfo* m_info;
4009 RunStatus m_runStatus;
4010 SectionInfo m_rootSection;
4011 SectionInfo* m_currentSection;
Phil Nash3c20a752011-06-23 08:23:33 +01004012 bool m_changed;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004013 };
4014
4015 ///////////////////////////////////////////////////////////////////////////
4016 ///////////////////////////////////////////////////////////////////////////
4017 class Runner : public IResultCapture, public IRunner
4018 {
4019 Runner( const Runner& );
4020 void operator =( const Runner& );
4021
4022 public:
4023
4024 ///////////////////////////////////////////////////////////////////////////
4025 explicit Runner
4026 (
4027 const Config& config
4028 )
4029 : m_runningTest( NULL ),
4030 m_config( config ),
Phil Nash89d1e6c2011-05-24 08:23:02 +01004031 m_reporter( m_config.getReporter() ),
4032 m_prevRunner( &Hub::getRunner() ),
4033 m_prevResultCapture( &Hub::getResultCapture() )
4034 {
4035 Hub::setRunner( this );
4036 Hub::setResultCapture( this );
4037 m_reporter->StartTesting();
4038 }
4039
4040 ///////////////////////////////////////////////////////////////////////////
4041 ~Runner
4042 ()
4043 {
Phil Nashf7299fc2012-02-25 09:39:45 +00004044 m_reporter->EndTesting( m_totals );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004045 Hub::setRunner( m_prevRunner );
4046 Hub::setResultCapture( m_prevResultCapture );
4047 }
4048
4049 ///////////////////////////////////////////////////////////////////////////
4050 virtual void runAll
4051 (
4052 bool runHiddenTests = false
4053 )
4054 {
4055 std::vector<TestCaseInfo> allTests = Hub::getTestCaseRegistry().getAllTests();
4056 for( std::size_t i=0; i < allTests.size(); ++i )
4057 {
4058 if( runHiddenTests || !allTests[i].isHidden() )
4059 runTest( allTests[i] );
4060 }
4061 }
4062
4063 ///////////////////////////////////////////////////////////////////////////
4064 virtual std::size_t runMatching
4065 (
4066 const std::string& rawTestSpec
4067 )
4068 {
4069 TestSpec testSpec( rawTestSpec );
4070
4071 std::vector<TestCaseInfo> allTests = Hub::getTestCaseRegistry().getAllTests();
4072 std::size_t testsRun = 0;
4073 for( std::size_t i=0; i < allTests.size(); ++i )
4074 {
4075 if( testSpec.matches( allTests[i].getName() ) )
4076 {
4077 runTest( allTests[i] );
4078 testsRun++;
4079 }
4080 }
4081 return testsRun;
4082 }
4083
4084 ///////////////////////////////////////////////////////////////////////////
4085 void runTest
4086 (
4087 const TestCaseInfo& testInfo
4088 )
4089 {
Phil Nashf7299fc2012-02-25 09:39:45 +00004090 Totals prevTotals = m_totals;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004091
4092 std::string redirectedCout;
4093 std::string redirectedCerr;
4094
4095 m_reporter->StartTestCase( testInfo );
4096
4097 m_runningTest = new RunningTest( &testInfo );
4098
4099 do
4100 {
4101 do
4102 {
4103 m_currentResult.setFileAndLine( m_runningTest->getTestCaseInfo().getFilename(),
4104 m_runningTest->getTestCaseInfo().getLine() );
4105 runCurrentTest( redirectedCout, redirectedCerr );
4106 }
4107 while( m_runningTest->hasUntestedSections() );
4108 }
4109 while( Hub::advanceGeneratorsForCurrentTest() );
4110
4111 delete m_runningTest;
4112 m_runningTest = NULL;
4113
Phil Nashf7299fc2012-02-25 09:39:45 +00004114 if( m_totals.assertions.failed > prevTotals.assertions.failed )
4115 ++m_totals.testCases.failed;
4116 else
4117 ++m_totals.testCases.passed;
4118
4119 m_reporter->EndTestCase( testInfo, m_totals - prevTotals, redirectedCout, redirectedCerr );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004120 }
4121
4122 ///////////////////////////////////////////////////////////////////////////
Phil Nashf7299fc2012-02-25 09:39:45 +00004123 virtual Totals getTotals
Phil Nash89d1e6c2011-05-24 08:23:02 +01004124 ()
4125 const
4126 {
Phil Nashf7299fc2012-02-25 09:39:45 +00004127 return m_totals;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004128 }
4129
4130 private: // IResultCapture
4131
4132 ///////////////////////////////////////////////////////////////////////////
4133 virtual ResultAction::Value acceptResult
4134 (
4135 bool result
4136 )
4137 {
4138 return acceptResult( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
4139 }
4140
4141 ///////////////////////////////////////////////////////////////////////////
4142 virtual ResultAction::Value acceptResult
4143 (
4144 ResultWas::OfType result
4145 )
4146 {
4147 m_currentResult.setResultType( result );
4148 return actOnCurrentResult();
4149 }
4150
4151 ///////////////////////////////////////////////////////////////////////////
4152 virtual ResultAction::Value acceptExpression
4153 (
4154 const MutableResultInfo& resultInfo
4155 )
4156 {
4157 m_currentResult = resultInfo;
4158 return actOnCurrentResult();
4159 }
4160
4161 ///////////////////////////////////////////////////////////////////////////
4162 virtual void acceptMessage
4163 (
4164 const std::string& msg
4165 )
4166 {
4167 m_currentResult.setMessage( msg );
4168 }
4169
4170 ///////////////////////////////////////////////////////////////////////////
4171 virtual void testEnded
4172 (
4173 const ResultInfo& result
4174 )
4175 {
4176 if( result.getResultType() == ResultWas::Ok )
4177 {
Phil Nashf7299fc2012-02-25 09:39:45 +00004178 m_totals.assertions.passed++;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004179 }
4180 else if( !result.ok() )
4181 {
Phil Nashf7299fc2012-02-25 09:39:45 +00004182 m_totals.assertions.failed++;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004183
4184 std::vector<ResultInfo>::const_iterator it = m_info.begin();
4185 std::vector<ResultInfo>::const_iterator itEnd = m_info.end();
4186 for(; it != itEnd; ++it )
4187 m_reporter->Result( *it );
4188 m_info.clear();
4189 }
4190
4191 if( result.getResultType() == ResultWas::Info )
4192 m_info.push_back( result );
4193 else
4194 m_reporter->Result( result );
4195 }
4196
4197 ///////////////////////////////////////////////////////////////////////////
4198 virtual bool sectionStarted
4199 (
4200 const std::string& name,
4201 const std::string& description,
4202 const std::string& filename,
4203 std::size_t line,
Phil Nashf7299fc2012-02-25 09:39:45 +00004204 Counts& assertions
Phil Nash89d1e6c2011-05-24 08:23:02 +01004205 )
4206 {
4207 std::ostringstream oss;
Phil Nash6e0f58d2012-02-15 18:37:21 +00004208 oss << name << "@" << SourceLineInfo( filename, line );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004209
4210 if( !m_runningTest->addSection( oss.str() ) )
4211 return false;
4212
4213 m_currentResult.setFileAndLine( filename, line );
4214 m_reporter->StartSection( name, description );
Phil Nashf7299fc2012-02-25 09:39:45 +00004215 assertions = m_totals.assertions;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004216
4217 return true;
4218 }
4219
4220 ///////////////////////////////////////////////////////////////////////////
4221 virtual void sectionEnded
4222 (
4223 const std::string& name,
Phil Nashf7299fc2012-02-25 09:39:45 +00004224 const Counts& prevAssertions
Phil Nash89d1e6c2011-05-24 08:23:02 +01004225 )
4226 {
4227 m_runningTest->endSection( name );
Phil Nashf7299fc2012-02-25 09:39:45 +00004228 m_reporter->EndSection( name, m_totals.assertions - prevAssertions );
Phil Nash89d1e6c2011-05-24 08:23:02 +01004229 }
4230
4231 ///////////////////////////////////////////////////////////////////////////
4232 virtual void pushScopedInfo
4233 (
4234 ScopedInfo* scopedInfo
4235 )
4236 {
4237 m_scopedInfos.push_back( scopedInfo );
4238 }
4239
4240 ///////////////////////////////////////////////////////////////////////////
4241 virtual void popScopedInfo
4242 (
4243 ScopedInfo* scopedInfo
4244 )
4245 {
4246 if( m_scopedInfos.back() == scopedInfo )
4247 m_scopedInfos.pop_back();
4248 }
4249
4250 ///////////////////////////////////////////////////////////////////////////
4251 virtual bool shouldDebugBreak
4252 ()
4253 const
4254 {
4255 return m_config.shouldDebugBreak();
4256 }
4257
4258 ///////////////////////////////////////////////////////////////////////////
4259 virtual std::string getCurrentTestName
4260 ()
4261 const
4262 {
4263 return m_runningTest
4264 ? m_runningTest->getTestCaseInfo().getName()
4265 : "";
4266 }
4267
Phil Nasha162e222012-02-10 08:30:13 +00004268 ///////////////////////////////////////////////////////////////////////////
4269 virtual const ResultInfo* getLastResult
4270 ()
4271 const
4272 {
4273 return &m_lastResult;
4274 }
4275
Phil Nash89d1e6c2011-05-24 08:23:02 +01004276 private:
4277
4278 ///////////////////////////////////////////////////////////////////////////
4279 ResultAction::Value actOnCurrentResult
4280 ()
4281 {
4282 testEnded( m_currentResult );
Phil Nasha162e222012-02-10 08:30:13 +00004283 m_lastResult = m_currentResult;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004284
Phil Nash89d1e6c2011-05-24 08:23:02 +01004285 m_currentResult = MutableResultInfo();
Phil Nasha162e222012-02-10 08:30:13 +00004286 if( m_lastResult.ok() )
Phil Nash89d1e6c2011-05-24 08:23:02 +01004287 return ResultAction::None;
4288 else if( shouldDebugBreak() )
4289 return ResultAction::DebugFailed;
4290 else
4291 return ResultAction::Failed;
4292 }
4293
4294 ///////////////////////////////////////////////////////////////////////////
4295 void runCurrentTest
4296 (
4297 std::string& redirectedCout,
4298 std::string& redirectedCerr
4299 )
4300 {
4301 try
4302 {
4303 m_runningTest->reset();
Phil Nash333e6e62012-02-17 19:50:59 +00004304 if( m_reporter->shouldRedirectStdout() )
4305 {
4306 StreamRedirect coutRedir( std::cout, redirectedCout );
4307 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
4308 m_runningTest->getTestCaseInfo().invoke();
4309 }
4310 else
4311 {
4312 m_runningTest->getTestCaseInfo().invoke();
4313 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004314 m_runningTest->ranToCompletion();
4315 }
4316 catch( TestFailureException& )
4317 {
4318 // This just means the test was aborted due to failure
4319 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01004320 catch(...)
4321 {
4322 acceptMessage( Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() );
4323 acceptResult( ResultWas::ThrewException );
4324 }
4325 m_info.clear();
4326 }
4327
4328 private:
4329 RunningTest* m_runningTest;
4330 MutableResultInfo m_currentResult;
Phil Nasha162e222012-02-10 08:30:13 +00004331 ResultInfo m_lastResult;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004332
4333 const Config& m_config;
Phil Nashf7299fc2012-02-25 09:39:45 +00004334 Totals m_totals;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004335 IReporter* m_reporter;
4336 std::vector<ScopedInfo*> m_scopedInfos;
4337 std::vector<ResultInfo> m_info;
4338 IRunner* m_prevRunner;
4339 IResultCapture* m_prevResultCapture;
4340 };
4341}
4342
4343// #included from: catch_generators_impl.hpp
4344
4345/*
4346 * catch_generators_impl.hpp
4347 * Catch
4348 *
4349 * Created by Phil on 28/01/2011.
4350 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
4351 *
4352 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4353 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4354 *
4355 */
4356
4357#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
4358
4359
4360#include <vector>
4361#include <string>
4362#include <map>
4363
4364namespace Catch
4365{
4366 struct GeneratorInfo
4367 {
4368 ///////////////////////////////////////////////////////////////////////
4369 GeneratorInfo
4370 (
4371 std::size_t size
4372 )
4373 : m_size( size ),
4374 m_currentIndex( 0 )
4375 {
4376 }
4377
4378 ///////////////////////////////////////////////////////////////////////
4379 bool moveNext
4380 ()
4381 {
4382 if( ++m_currentIndex == m_size )
4383 {
4384 m_currentIndex = 0;
4385 return false;
4386 }
4387 return true;
4388 }
4389
4390 ///////////////////////////////////////////////////////////////////////
4391 std::size_t getCurrentIndex
4392 ()
4393 const
4394 {
4395 return m_currentIndex;
4396 }
4397
4398 std::size_t m_size;
4399 std::size_t m_currentIndex;
4400 };
4401
4402 ///////////////////////////////////////////////////////////////////////////
4403 ///////////////////////////////////////////////////////////////////////////
4404
4405 class GeneratorsForTest
4406 {
4407
4408 public:
4409 ///////////////////////////////////////////////////////////////////////
4410 ~GeneratorsForTest
4411 ()
4412 {
4413 deleteAll( m_generatorsInOrder );
4414 }
4415
4416 ///////////////////////////////////////////////////////////////////////
4417 GeneratorInfo& getGeneratorInfo
4418 (
4419 const std::string& fileInfo,
4420 std::size_t size
4421 )
4422 {
4423 std::map<std::string, GeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
4424 if( it == m_generatorsByName.end() )
4425 {
4426 GeneratorInfo* info = new GeneratorInfo( size );
4427 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
4428 m_generatorsInOrder.push_back( info );
4429 return *info;
4430 }
4431 return *it->second;
4432 }
4433
4434 ///////////////////////////////////////////////////////////////////////
4435 bool moveNext
4436 ()
4437 {
4438 std::vector<GeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
4439 std::vector<GeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
4440 for(; it != itEnd; ++it )
4441 {
4442 if( (*it)->moveNext() )
4443 return true;
4444 }
4445 return false;
4446 }
4447
4448 private:
4449 std::map<std::string, GeneratorInfo*> m_generatorsByName;
4450 std::vector<GeneratorInfo*> m_generatorsInOrder;
4451 };
4452
4453} // end namespace Catch
4454
4455#define INTERNAL_CATCH_LINESTR2( line ) #line
4456#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
4457
4458#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
4459
Phil Nash918046a2012-02-28 20:04:42 +00004460// #included from: catch_console_colour_impl.hpp
4461
4462/*
4463 * catch_console_colour_impl.hpp
4464 * Catch
4465 *
4466 * Created by Phil on 25/2/2012.
4467 * Copyright 2012 Two Blue Cubes Ltd. All rights reserved.
4468 *
4469 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4470 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4471 *
4472 */
4473#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
4474
4475// #included from: catch_console_colour.hpp
4476
4477/*
4478 * catch_console_colour.hpp
4479 * Catch
4480 *
4481 * Created by Phil on 25/2/2012.
4482 * Copyright 2012 Two Blue Cubes Ltd. All rights reserved.
4483 *
4484 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4485 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4486 *
4487 */
4488#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
4489
4490
4491namespace Catch
4492{
4493 struct ConsoleColourImpl;
4494
4495 class TextColour : NonCopyable
4496 {
4497 public:
4498
4499 enum Colours
4500 {
4501 None,
4502
4503 FileName,
4504 ResultError,
4505 ResultSuccess,
4506
4507 Error,
4508 Success,
4509
4510 OriginalExpression,
4511 ReconstructedExpression
4512 };
4513
4514 TextColour( Colours colour = None );
4515 void set( Colours colour );
4516 ~TextColour();
4517
4518 private:
4519 ConsoleColourImpl* m_impl;
4520 };
4521
4522} // end namespace Catch
4523
4524
4525#ifdef CATCH_PLATFORM_WINDOWS
4526
4527#include <windows.h>
4528
4529namespace Catch
4530{
4531 namespace
4532 {
4533 WORD mapConsoleColour( TextColour::Colours colour )
4534 {
4535 switch( colour )
4536 {
4537 case TextColour::FileName:
4538 return FOREGROUND_INTENSITY; // greyed out
4539 case TextColour::ResultError:
4540 return FOREGROUND_RED | FOREGROUND_INTENSITY; // bright red
4541 case TextColour::ResultSuccess:
4542 return FOREGROUND_GREEN | FOREGROUND_INTENSITY; // bright green
4543 case TextColour::Error:
4544 return FOREGROUND_RED; // dark red
4545 case TextColour::Success:
4546 return FOREGROUND_GREEN; // dark green
4547 case TextColour::OriginalExpression:
4548 return FOREGROUND_BLUE | FOREGROUND_GREEN; // turquoise
4549 case TextColour::ReconstructedExpression:
4550 return FOREGROUND_RED | FOREGROUND_GREEN; // greeny-yellow
4551 default: return 0;
4552 }
4553 }
4554 }
4555
4556 struct ConsoleColourImpl
4557 {
4558 ConsoleColourImpl()
4559 : hStdout( GetStdHandle(STD_OUTPUT_HANDLE) ),
4560 wOldColorAttrs( 0 )
4561 {
4562 GetConsoleScreenBufferInfo( hStdout, &csbiInfo );
4563 wOldColorAttrs = csbiInfo.wAttributes;
4564 }
4565 ~ConsoleColourImpl()
4566 {
4567 SetConsoleTextAttribute( hStdout, wOldColorAttrs );
4568 }
4569 void set( TextColour::Colours colour )
4570 {
4571 WORD consoleColour = mapConsoleColour( colour );
4572 if( consoleColour > 0 )
4573 SetConsoleTextAttribute( hStdout, consoleColour );
4574 }
4575
4576 HANDLE hStdout;
4577 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
4578 WORD wOldColorAttrs;
4579 };
4580
4581 TextColour::TextColour( Colours colour )
4582 : m_impl( new ConsoleColourImpl() )
4583 {
4584 if( colour )
4585 m_impl->set( colour );
4586 }
4587 TextColour::~TextColour()
4588 {
4589 delete m_impl;
4590 }
4591 void TextColour::set( Colours colour )
4592 {
4593 m_impl->set( colour );
4594 }
4595
4596} // end namespace Catch
4597
4598#else
4599
4600namespace Catch
4601{
4602 TextColour::TextColour( Colours ){}
4603 TextColour::~TextColour(){}
4604 void TextColour::set( Colours ){}
4605
4606} // end namespace Catch
4607
4608#endif
4609
Phil Nash89d1e6c2011-05-24 08:23:02 +01004610// #included from: catch_stream.hpp
4611
4612/*
4613 * catch_stream.hpp
4614 * Catch
4615 *
4616 * Created by Phil on 17/01/2011.
4617 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
4618 *
4619 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4620 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4621 *
4622 */
4623
4624#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
4625
4626#include <stdexcept>
4627#include <cstdio>
4628
4629namespace Catch
4630{
4631 template<typename WriterF, size_t bufferSize=256>
4632 class StreamBufImpl : public StreamBufBase
4633 {
4634 char data[bufferSize];
4635 WriterF m_writer;
4636
4637 public:
4638 ///////////////////////////////////////////////////////////////////////
4639 StreamBufImpl
4640 ()
4641 {
4642 setp( data, data + sizeof(data) );
4643 }
4644
4645 ///////////////////////////////////////////////////////////////////////
4646 ~StreamBufImpl
4647 ()
4648 {
4649 sync();
4650 }
4651
4652 private:
4653 ///////////////////////////////////////////////////////////////////////
4654 int overflow
4655 (
4656 int c
4657 )
4658 {
4659 sync();
4660
4661 if( c != EOF )
4662 {
4663 if( pbase() == epptr() )
4664 m_writer( std::string( 1, static_cast<char>( c ) ) );
4665 else
4666 sputc( static_cast<char>( c ) );
4667 }
4668 return 0;
4669 }
4670
4671 ///////////////////////////////////////////////////////////////////////
4672 int sync
4673 ()
4674 {
4675 if( pbase() != pptr() )
4676 {
4677 m_writer( std::string( pbase(), pptr() - pbase() ) );
4678 setp( pbase(), epptr() );
4679 }
4680 return 0;
4681 }
4682 };
4683
4684 ///////////////////////////////////////////////////////////////////////////
4685 ///////////////////////////////////////////////////////////////////////////
4686
4687 struct OutputDebugWriter
4688 {
4689 ///////////////////////////////////////////////////////////////////////
4690 void operator()
4691 (
4692 const std::string &str
4693 )
4694 {
4695 writeToDebugConsole( str );
4696 }
4697 };
4698}
4699
4700
4701namespace Catch
4702{
4703 ///////////////////////////////////////////////////////////////////////////
4704 Hub::Hub
4705 ()
4706 : m_reporterRegistry( new ReporterRegistry ),
4707 m_testCaseRegistry( new TestRegistry ),
4708 m_exceptionTranslatorRegistry( new ExceptionTranslatorRegistry )
4709 {
4710 }
4711
4712 ///////////////////////////////////////////////////////////////////////////
4713 Hub& Hub::me
4714 ()
4715 {
Phil Nashdd5b9c22012-02-18 09:58:30 +00004716 Hub*& hub = singleInstance();
4717 if( !hub )
4718 hub = new Hub();
4719 return *hub;
4720 }
4721
4722 ///////////////////////////////////////////////////////////////////////////
4723 void Hub::cleanUp
4724 ()
4725 {
4726 Hub*& hub = singleInstance();
4727 delete hub;
4728 hub = NULL;
4729 }
4730
4731 ///////////////////////////////////////////////////////////////////////////
4732 Hub*& Hub::singleInstance()
4733 {
4734 static Hub* hub = NULL;
Phil Nash89d1e6c2011-05-24 08:23:02 +01004735 return hub;
Phil Nashdd5b9c22012-02-18 09:58:30 +00004736
Phil Nash89d1e6c2011-05-24 08:23:02 +01004737 }
4738
4739 ///////////////////////////////////////////////////////////////////////////
4740 void Hub::setRunner( IRunner* runner )
4741 {
4742 me().m_runner = runner;
4743 }
4744 ///////////////////////////////////////////////////////////////////////////
4745 void Hub::setResultCapture( IResultCapture* resultCapture )
4746 {
4747 me().m_resultCapture = resultCapture;
4748 }
4749
4750 ///////////////////////////////////////////////////////////////////////////
4751 IResultCapture& Hub::getResultCapture
4752 ()
4753 {
4754 return *me().m_resultCapture;
4755 }
4756
4757 ///////////////////////////////////////////////////////////////////////////
4758 IRunner& Hub::getRunner
4759 ()
4760 {
4761 return *me().m_runner;
4762 }
4763
4764 ///////////////////////////////////////////////////////////////////////////
4765 IReporterRegistry& Hub::getReporterRegistry
4766 ()
4767 {
4768 return *me().m_reporterRegistry.get();
4769 }
4770
4771 ///////////////////////////////////////////////////////////////////////////
4772 ITestCaseRegistry& Hub::getTestCaseRegistry
4773 ()
4774 {
4775 return *me().m_testCaseRegistry.get();
4776 }
4777
4778 ///////////////////////////////////////////////////////////////////////////
4779 IExceptionTranslatorRegistry& Hub::getExceptionTranslatorRegistry
4780 ()
4781 {
4782 return *me().m_exceptionTranslatorRegistry.get();
4783 }
4784
4785 ///////////////////////////////////////////////////////////////////////////
4786 std::streambuf* Hub::createStreamBuf
4787 (
4788 const std::string& streamName
4789 )
4790 {
4791 if( streamName == "stdout" ) return std::cout.rdbuf();
4792 if( streamName == "stderr" ) return std::cerr.rdbuf();
4793 if( streamName == "debug" ) return new StreamBufImpl<OutputDebugWriter>;
4794
4795 throw std::domain_error( "Unknown stream: " + streamName );
4796 }
4797
4798 ///////////////////////////////////////////////////////////////////////////
4799 GeneratorsForTest* Hub::findGeneratorsForCurrentTest
4800 ()
4801 {
4802 std::string testName = getResultCapture().getCurrentTestName();
4803
4804 std::map<std::string, GeneratorsForTest*>::const_iterator it =
4805 m_generatorsByTestName.find( testName );
4806 return it != m_generatorsByTestName.end()
4807 ? it->second
4808 : NULL;
4809 }
4810 ///////////////////////////////////////////////////////////////////////////
4811 GeneratorsForTest& Hub::getGeneratorsForCurrentTest
4812 ()
4813 {
4814 GeneratorsForTest* generators = findGeneratorsForCurrentTest();
4815 if( !generators )
4816 {
4817 std::string testName = getResultCapture().getCurrentTestName();
4818 generators = new GeneratorsForTest();
4819 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
4820 }
4821 return *generators;
4822 }
4823
4824 ///////////////////////////////////////////////////////////////////////////
4825 size_t Hub::getGeneratorIndex
4826 (
4827 const std::string& fileInfo,
4828 size_t totalSize
4829 )
4830 {
4831 return me().getGeneratorsForCurrentTest()
4832 .getGeneratorInfo( fileInfo, totalSize )
4833 .getCurrentIndex();
4834 }
4835
4836 ///////////////////////////////////////////////////////////////////////////
4837 bool Hub::advanceGeneratorsForCurrentTest
4838 ()
4839 {
4840 GeneratorsForTest* generators = me().findGeneratorsForCurrentTest();
4841 return generators && generators->moveNext();
4842 }
4843}
4844
4845// #included from: internal/catch_commandline.hpp
4846
4847/*
4848 * catch_commandline.hpp
4849 * Catch
4850 *
4851 * Created by Phil on 02/11/2010.
4852 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
4853 *
4854 * Distributed under the Boost Software License, Version 1.0. (See accompanying
4855 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4856 *
4857 */
4858
4859#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
4860
4861
4862namespace Catch
4863{
4864 // !TBD: This could be refactored to be more "declarative"
4865 // have a table up front that relates the mode, option strings, # arguments, names of arguments
4866 // - may not be worth it at this scale
4867
4868 // -l, --list tests [xml] lists available tests (optionally in xml)
4869 // -l, --list reporters [xml] lists available reports (optionally in xml)
4870 // -l, --list all [xml] lists available tests and reports (optionally in xml)
4871 // -t, --test "testspec" ["testspec", ...]
4872 // -r, --reporter <type>
4873 // -o, --out filename to write to
4874 // -s, --success report successful cases too
4875 // -b, --break breaks into debugger on test failure
4876 // -n, --name specifies an optional name for the test run
4877 class ArgParser : NonCopyable
4878 {
4879 enum Mode
4880 {
4881 modeNone,
4882 modeList,
4883 modeTest,
4884 modeReport,
4885 modeOutput,
4886 modeSuccess,
4887 modeBreak,
4888 modeName,
4889 modeHelp,
4890
4891 modeError
4892 };
4893
4894 public:
4895 ///////////////////////////////////////////////////////////////////////
4896 ArgParser
4897 (
4898 int argc,
4899 char * const argv[],
4900 Config& config
4901 )
4902 : m_mode( modeNone ),
4903 m_config( config )
4904 {
4905 for( int i=1; i < argc; ++i )
4906 {
4907 if( argv[i][0] == '-' )
4908 {
4909 std::string cmd = ( argv[i] );
4910 if( cmd == "-l" || cmd == "--list" )
4911 changeMode( cmd, modeList );
4912 else if( cmd == "-t" || cmd == "--test" )
4913 changeMode( cmd, modeTest );
4914 else if( cmd == "-r" || cmd == "--reporter" )
4915 changeMode( cmd, modeReport );
4916 else if( cmd == "-o" || cmd == "--out" )
4917 changeMode( cmd, modeOutput );
4918 else if( cmd == "-s" || cmd == "--success" )
4919 changeMode( cmd, modeSuccess );
4920 else if( cmd == "-b" || cmd == "--break" )
4921 changeMode( cmd, modeBreak );
4922 else if( cmd == "-n" || cmd == "--name" )
4923 changeMode( cmd, modeName );
4924 else if( cmd == "-h" || cmd == "-?" || cmd == "--help" )
4925 changeMode( cmd, modeHelp );
4926 }
4927 else
4928 {
4929 m_args.push_back( argv[i] );
4930 }
4931 if( m_mode == modeError )
4932 return;
4933 }
4934 changeMode( "", modeNone );
4935 }
4936
4937 private:
4938 ///////////////////////////////////////////////////////////////////////
4939 std::string argsAsString
4940 ()
4941 {
4942 std::ostringstream oss;
4943 std::vector<std::string>::const_iterator it = m_args.begin();
4944 std::vector<std::string>::const_iterator itEnd = m_args.end();
4945 for( bool first = true; it != itEnd; ++it, first = false )
4946 {
4947 if( !first )
4948 oss << " ";
4949 oss << *it;
4950 }
4951 return oss.str();
4952 }
4953
4954 ///////////////////////////////////////////////////////////////////////
4955 void changeMode
4956 (
4957 const std::string& cmd,
4958 Mode mode
4959 )
4960 {
4961 m_command = cmd;
4962 switch( m_mode )
4963 {
4964 case modeNone:
4965 if( m_args.size() > 0 )
4966 return setErrorMode( "Unexpected arguments before " + m_command + ": " + argsAsString() );
4967 break;
4968 case modeList:
4969 if( m_args.size() > 2 )
4970 {
4971 return setErrorMode( m_command + " expected upto 2 arguments but recieved: " + argsAsString() );
4972 }
4973 else
4974 {
4975 Config::List::What listSpec = Config::List::All;
4976 if( m_args.size() >= 1 )
4977 {
4978 if( m_args[0] == "tests" )
4979 listSpec = Config::List::Tests;
4980 else if( m_args[0] == "reporters" )
4981 listSpec = Config::List::Reports;
4982 else
4983 return setErrorMode( m_command + " expected [tests] or [reporters] but recieved: [" + m_args[0] + "]" );
4984 }
4985 if( m_args.size() >= 2 )
4986 {
4987 if( m_args[1] == "xml" )
4988 listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsXml );
4989 else if( m_args[1] == "text" )
4990 listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsText );
4991 else
4992 return setErrorMode( m_command + " expected [xml] or [text] but recieved: [" + m_args[1] + "]" );
4993 }
4994 m_config.setListSpec( static_cast<Config::List::What>( m_config.getListSpec() | listSpec ) );
4995 }
4996 break;
4997 case modeTest:
4998 if( m_args.size() == 0 )
4999 return setErrorMode( m_command + " expected at least 1 argument but recieved none" );
5000 {
5001 std::vector<std::string>::const_iterator it = m_args.begin();
5002 std::vector<std::string>::const_iterator itEnd = m_args.end();
5003 for(; it != itEnd; ++it )
5004 m_config.addTestSpec( *it );
5005 }
5006 break;
5007 case modeReport:
5008 if( m_args.size() != 1 )
5009 return setErrorMode( m_command + " expected one argument, recieved: " + argsAsString() );
5010 m_config.setReporter( m_args[0] );
5011 break;
5012 case modeOutput:
5013 if( m_args.size() == 0 )
5014 return setErrorMode( m_command + " expected filename" );
5015 if( m_args[0][0] == '%' )
5016 m_config.useStream( m_args[0].substr( 1 ) );
5017 else
5018 m_config.setFilename( m_args[0] );
5019 break;
5020 case modeSuccess:
5021 if( m_args.size() != 0 )
5022 return setErrorMode( m_command + " does not accept arguments" );
5023 m_config.setIncludeWhat( Config::Include::SuccessfulResults );
5024 break;
5025 case modeBreak:
5026 if( m_args.size() != 0 )
5027 return setErrorMode( m_command + " does not accept arguments" );
5028 m_config.setShouldDebugBreak( true );
5029 break;
5030 case modeName:
5031 if( m_args.size() != 1 )
5032 return setErrorMode( m_command + " requires exactly one argument (a name)" );
5033 m_config.setName( m_args[0] );
5034 break;
5035 case modeHelp:
5036 if( m_args.size() != 0 )
5037 return setErrorMode( m_command + " does not accept arguments" );
5038 m_config.setShowHelp( true );
5039 break;
Phil Nashf51d3162011-12-28 10:37:31 +00005040 case modeError:
Phil Nash89d1e6c2011-05-24 08:23:02 +01005041 default:
5042 break;
5043 }
5044 m_args.clear();
5045 m_mode = mode;
5046 }
5047
5048 ///////////////////////////////////////////////////////////////////////
5049 void setErrorMode
5050 (
5051 const std::string& errorMessage
5052 )
5053 {
5054 m_mode = modeError;
5055 m_command = "";
5056 m_config.setError( errorMessage );
5057 }
5058
5059 private:
5060
5061 Mode m_mode;
5062 std::string m_command;
5063 std::vector<std::string> m_args;
5064 Config& m_config;
5065 };
5066
5067
5068} // end namespace Catch
5069
5070// #included from: internal/catch_list.hpp
5071
5072/*
5073 * catch_list.hpp
5074 * Catch
5075 *
5076 * Created by Phil on 5/11/2010.
5077 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
5078 *
5079 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5080 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5081 *
5082 */
5083
5084#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
5085
5086#include <limits>
5087
5088namespace Catch
5089{
5090 ///////////////////////////////////////////////////////////////////////////
5091 inline int List
5092 (
5093 const Config& config
5094 )
5095 {
5096 if( config.listWhat() & Config::List::Reports )
5097 {
5098 std::cout << "Available reports:\n";
5099 IReporterRegistry::FactoryMap::const_iterator it = Hub::getReporterRegistry().getFactories().begin();
5100 IReporterRegistry::FactoryMap::const_iterator itEnd = Hub::getReporterRegistry().getFactories().end();
5101 for(; it != itEnd; ++it )
5102 {
5103 // !TBD: consider listAs()
5104 std::cout << "\t" << it->first << "\n\t\t'" << it->second->getDescription() << "'\n";
5105 }
5106 std::cout << std::endl;
5107 }
5108 if( config.listWhat() & Config::List::Tests )
5109 {
5110 std::cout << "Available tests:\n";
5111 std::vector<TestCaseInfo>::const_iterator it = Hub::getTestCaseRegistry().getAllTests().begin();
5112 std::vector<TestCaseInfo>::const_iterator itEnd = Hub::getTestCaseRegistry().getAllTests().end();
5113 for(; it != itEnd; ++it )
5114 {
5115 // !TBD: consider listAs()
5116 std::cout << "\t" << it->getName() << "\n\t\t '" << it->getDescription() << "'\n";
5117 }
5118 std::cout << std::endl;
5119 }
5120 if( ( config.listWhat() & Config::List::All ) == 0 )
5121 {
5122 std::cerr << "Unknown list type" << std::endl;
5123 return (std::numeric_limits<int>::max)();
5124 }
5125
5126 if( config.getReporter() )
5127 {
5128 std::cerr << "Reporters ignored when listing" << std::endl;
5129 }
5130 if( !config.testsSpecified() )
5131 {
5132 std::cerr << "Test specs ignored when listing" << std::endl;
5133 }
5134 return 0;
5135
5136 }
5137
5138} // end namespace Catch
5139
5140// #included from: reporters/catch_reporter_basic.hpp
5141
5142/*
5143 * catch_reporter_basic.hpp
5144 * Catch
5145 *
5146 * Created by Phil on 28/10/2010.
5147 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
5148 *
5149 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5150 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5151 *
5152 */
5153#define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
5154
Phil Nashf721a962011-06-07 14:13:57 +01005155// #included from: ../internal/catch_reporter_registrars.hpp
Phil Nash89d1e6c2011-05-24 08:23:02 +01005156
5157/*
5158 * catch_reporter_registrars.hpp
5159 * Test
5160 *
5161 * Created by Phil on 31/12/2010.
5162 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
5163 *
5164 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5165 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5166 *
5167 */
5168#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
5169
5170
5171namespace Catch
5172{
5173 template<typename T>
5174 class ReporterRegistrar
5175 {
5176 class ReporterFactory : public IReporterFactory
5177 {
5178 ///////////////////////////////////////////////////////////////////
5179 virtual IReporter* create
5180 (
5181 const IReporterConfig& config
5182 )
5183 const
5184 {
5185 return new T( config );
5186 }
5187 ///////////////////////////////////////////////////////////////////
5188 virtual std::string getDescription
5189 ()
5190 const
5191 {
5192 return T::getDescription();
5193 }
5194 };
5195
5196 public:
5197
5198 ///////////////////////////////////////////////////////////////////////
5199 ReporterRegistrar
5200 (
5201 const std::string& name
5202 )
5203 {
5204 Hub::getReporterRegistry().registerReporter( name, new ReporterFactory() );
5205 }
5206 };
5207}
5208
5209///////////////////////////////////////////////////////////////////////////////
5210#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
5211 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
5212
5213
5214namespace Catch
5215{
Phil Nashf7299fc2012-02-25 09:39:45 +00005216 struct pluralise
5217 {
5218 pluralise( std::size_t count, const std::string& label )
5219 : m_count( count ),
5220 m_label( label )
5221 {}
5222
5223 friend std::ostream& operator << ( std::ostream& os, const pluralise& pluraliser )
5224 {
5225 os << pluraliser.m_count << " " << pluraliser.m_label;
5226 if( pluraliser.m_count != 1 )
5227 os << "s";
5228 return os;
5229 }
5230
5231 std::size_t m_count;
5232 std::string m_label;
5233 };
5234
Phil Nash89d1e6c2011-05-24 08:23:02 +01005235 class BasicReporter : public IReporter
5236 {
5237 struct SpanInfo
5238 {
5239 SpanInfo()
5240 : emitted( false )
5241 {}
5242
5243 SpanInfo( const std::string& spanName )
5244 : name( spanName ),
5245 emitted( false )
5246 {}
5247
5248 SpanInfo( const SpanInfo& other )
5249 : name( other.name ),
5250 emitted( other.emitted )
5251 {}
5252
5253 std::string name;
5254 bool emitted;
5255 };
5256
5257 public:
5258 ///////////////////////////////////////////////////////////////////////////
5259 BasicReporter
5260 (
5261 const IReporterConfig& config
5262 )
Phil Nashf51d3162011-12-28 10:37:31 +00005263 : m_config( config ),
5264 m_firstSectionInTestCase( true )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005265 {
5266 }
5267
5268 ///////////////////////////////////////////////////////////////////////////
5269 static std::string getDescription
5270 ()
5271 {
5272 return "Reports test results as lines of text";
5273 }
5274
5275 private:
5276
5277 ///////////////////////////////////////////////////////////////////////////
5278 void ReportCounts
5279 (
Phil Nashf7299fc2012-02-25 09:39:45 +00005280 const std::string& label,
5281 const Counts& counts
Phil Nash89d1e6c2011-05-24 08:23:02 +01005282 )
5283 {
Phil Nash918046a2012-02-28 20:04:42 +00005284 if( counts.passed )
5285 m_config.stream() << counts.failed << " of " << counts.total() << " " << label << "s failed";
Phil Nash89d1e6c2011-05-24 08:23:02 +01005286 else
Phil Nash918046a2012-02-28 20:04:42 +00005287 m_config.stream() << ( counts.failed > 1 ? "All " : "" ) << pluralise( counts.failed, label ) << " failed";
Phil Nashf7299fc2012-02-25 09:39:45 +00005288 }
Phil Nash2cc9b0d2012-02-22 09:44:06 +00005289
Phil Nashf7299fc2012-02-25 09:39:45 +00005290 ///////////////////////////////////////////////////////////////////////////
5291 void ReportCounts
5292 (
5293 const Totals& totals
5294 )
5295 {
5296 if( totals.assertions.total() == 0 )
5297 {
5298 m_config.stream() << "No tests ran";
Phil Nashf7299fc2012-02-25 09:39:45 +00005299 }
Phil Nash918046a2012-02-28 20:04:42 +00005300 else if( totals.assertions.failed )
Phil Nashf7299fc2012-02-25 09:39:45 +00005301 {
Phil Nash918046a2012-02-28 20:04:42 +00005302 TextColour colour( TextColour::ResultError );
5303 ReportCounts( "test case", totals.testCases );
5304 if( totals.testCases.failed > 0 )
5305 {
5306 m_config.stream() << " (";
5307 ReportCounts( "assertion", totals.assertions );
5308 m_config.stream() << ")";
5309 }
5310 }
5311 else
5312 {
5313 TextColour colour( TextColour::ResultSuccess );
5314 m_config.stream() << "All tests passed ("
5315 << pluralise( totals.assertions.passed, "assertion" ) << " in "
5316 << pluralise( totals.testCases.passed, "test case" ) << ")";
Phil Nash2cc9b0d2012-02-22 09:44:06 +00005317 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01005318 }
5319
5320 private: // IReporter
5321
5322 ///////////////////////////////////////////////////////////////////////////
Phil Nash333e6e62012-02-17 19:50:59 +00005323 virtual bool shouldRedirectStdout
5324 ()
5325 const
5326 {
5327 return false;
5328 }
5329
5330 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01005331 virtual void StartTesting
5332 ()
5333 {
5334 m_testingSpan = SpanInfo();
5335 }
5336
5337 ///////////////////////////////////////////////////////////////////////////
5338 virtual void EndTesting
5339 (
Phil Nashf7299fc2012-02-25 09:39:45 +00005340 const Totals& totals
Phil Nash89d1e6c2011-05-24 08:23:02 +01005341 )
5342 {
5343 // Output the overall test results even if "Started Testing" was not emitted
Phil Nash2cc9b0d2012-02-22 09:44:06 +00005344 m_config.stream() << "\n[Testing completed. ";
Phil Nashf7299fc2012-02-25 09:39:45 +00005345 ReportCounts( totals);
Phil Nash89d1e6c2011-05-24 08:23:02 +01005346 m_config.stream() << "]\n" << std::endl;
5347 }
5348
5349 ///////////////////////////////////////////////////////////////////////////
5350 virtual void StartGroup
5351 (
5352 const std::string& groupName
5353 )
5354 {
5355 m_groupSpan = groupName;
5356 }
5357
5358 ///////////////////////////////////////////////////////////////////////////
5359 virtual void EndGroup
5360 (
5361 const std::string& groupName,
Phil Nashf7299fc2012-02-25 09:39:45 +00005362 const Totals& totals
Phil Nash89d1e6c2011-05-24 08:23:02 +01005363 )
5364 {
5365 if( m_groupSpan.emitted && !groupName.empty() )
5366 {
5367 m_config.stream() << "[End of group: '" << groupName << "'. ";
Phil Nashf7299fc2012-02-25 09:39:45 +00005368 ReportCounts( totals );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005369 m_config.stream() << "]\n" << std::endl;
5370 m_groupSpan = SpanInfo();
5371 }
5372 }
5373
5374 ///////////////////////////////////////////////////////////////////////////
5375 virtual void StartTestCase
5376 (
5377 const TestCaseInfo& testInfo
5378 )
5379 {
5380 m_testSpan = testInfo.getName();
5381 }
5382
5383 ///////////////////////////////////////////////////////////////////////////
5384 virtual void StartSection
5385 (
5386 const std::string& sectionName,
5387 const std::string /*description*/
5388 )
5389 {
5390 m_sectionSpans.push_back( SpanInfo( sectionName ) );
5391 }
5392
5393 ///////////////////////////////////////////////////////////////////////////
5394 virtual void EndSection
5395 (
5396 const std::string& sectionName,
Phil Nashf7299fc2012-02-25 09:39:45 +00005397 const Counts& assertions
Phil Nash89d1e6c2011-05-24 08:23:02 +01005398 )
5399 {
5400 SpanInfo& sectionSpan = m_sectionSpans.back();
5401 if( sectionSpan.emitted && !sectionSpan.name.empty() )
5402 {
Phil Nash918046a2012-02-28 20:04:42 +00005403 m_config.stream() << "[End of section: '" << sectionName << "'";
5404
5405 if( assertions.failed )
5406 {
5407 TextColour colour( TextColour::ResultError );
5408 ReportCounts( "assertion", assertions);
5409 }
5410 else
5411 {
5412 TextColour colour( TextColour::ResultSuccess );
5413 m_config.stream() << ( assertions.passed > 1 ? "All " : "" )
5414 << pluralise( assertions.passed, "assertion" ) << "passed" ;
5415 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01005416 m_config.stream() << "]\n" << std::endl;
5417 }
5418 m_sectionSpans.pop_back();
5419 }
5420
5421 ///////////////////////////////////////////////////////////////////////////
5422 virtual void Result
5423 (
5424 const ResultInfo& resultInfo
5425 )
5426 {
5427 if( !m_config.includeSuccessfulResults() && resultInfo.getResultType() == ResultWas::Ok )
5428 return;
5429
5430 StartSpansLazily();
5431
5432 if( !resultInfo.getFilename().empty() )
Phil Nash918046a2012-02-28 20:04:42 +00005433 {
5434 TextColour colour( TextColour::FileName );
Phil Nash6e0f58d2012-02-15 18:37:21 +00005435 m_config.stream() << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
Phil Nash918046a2012-02-28 20:04:42 +00005436 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01005437
5438 if( resultInfo.hasExpression() )
5439 {
Phil Nash918046a2012-02-28 20:04:42 +00005440 TextColour colour( TextColour::OriginalExpression );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005441 m_config.stream() << resultInfo.getExpression();
5442 if( resultInfo.ok() )
Phil Nash918046a2012-02-28 20:04:42 +00005443 {
5444 TextColour colour( TextColour::Success );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005445 m_config.stream() << " succeeded";
Phil Nash918046a2012-02-28 20:04:42 +00005446 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01005447 else
Phil Nash918046a2012-02-28 20:04:42 +00005448 {
5449 TextColour colour( TextColour::Error );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005450 m_config.stream() << " failed";
Phil Nash918046a2012-02-28 20:04:42 +00005451 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01005452 }
5453 switch( resultInfo.getResultType() )
5454 {
5455 case ResultWas::ThrewException:
Phil Nash918046a2012-02-28 20:04:42 +00005456 {
5457 TextColour colour( TextColour::Error );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005458 if( resultInfo.hasExpression() )
5459 m_config.stream() << " with unexpected";
5460 else
5461 m_config.stream() << "Unexpected";
5462 m_config.stream() << " exception with message: '" << resultInfo.getMessage() << "'";
Phil Nash918046a2012-02-28 20:04:42 +00005463 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01005464 break;
5465 case ResultWas::DidntThrowException:
Phil Nash918046a2012-02-28 20:04:42 +00005466 {
5467 TextColour colour( TextColour::Error );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005468 if( resultInfo.hasExpression() )
5469 m_config.stream() << " because no exception was thrown where one was expected";
5470 else
5471 m_config.stream() << "No exception thrown where one was expected";
Phil Nash918046a2012-02-28 20:04:42 +00005472 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01005473 break;
5474 case ResultWas::Info:
5475 streamVariableLengthText( "info", resultInfo.getMessage() );
5476 break;
5477 case ResultWas::Warning:
5478 m_config.stream() << "warning:\n'" << resultInfo.getMessage() << "'";
5479 break;
5480 case ResultWas::ExplicitFailure:
Phil Nash918046a2012-02-28 20:04:42 +00005481 {
5482 TextColour colour( TextColour::Error );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005483 m_config.stream() << "failed with message: '" << resultInfo.getMessage() << "'";
Phil Nash918046a2012-02-28 20:04:42 +00005484 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01005485 break;
Phil Nashf51d3162011-12-28 10:37:31 +00005486 case ResultWas::Unknown: // These cases are here to prevent compiler warnings
5487 case ResultWas::Ok:
5488 case ResultWas::FailureBit:
5489 case ResultWas::ExpressionFailed:
5490 case ResultWas::Exception:
Phil Nash89d1e6c2011-05-24 08:23:02 +01005491 default:
5492 if( !resultInfo.hasExpression() )
5493 {
5494 if( resultInfo.ok() )
Phil Nash918046a2012-02-28 20:04:42 +00005495 {
5496 TextColour colour( TextColour::Success );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005497 m_config.stream() << " succeeded";
Phil Nash918046a2012-02-28 20:04:42 +00005498 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01005499 else
Phil Nash918046a2012-02-28 20:04:42 +00005500 {
5501 TextColour colour( TextColour::Error );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005502 m_config.stream() << " failed";
Phil Nash918046a2012-02-28 20:04:42 +00005503 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01005504 }
5505 break;
5506 }
5507
Phil Nash918046a2012-02-28 20:04:42 +00005508 if( resultInfo.hasExpression() && resultInfo.getExpression() != resultInfo.getExpandedExpression() )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005509 {
Phil Nash918046a2012-02-28 20:04:42 +00005510 m_config.stream() << " for: ";
5511 TextColour colour( TextColour::ReconstructedExpression );
5512 m_config.stream() << resultInfo.getExpandedExpression();
Phil Nash89d1e6c2011-05-24 08:23:02 +01005513 }
5514 m_config.stream() << std::endl;
5515 }
5516
5517 ///////////////////////////////////////////////////////////////////////////
5518 virtual void EndTestCase
5519 (
5520 const TestCaseInfo& testInfo,
Phil Nashf7299fc2012-02-25 09:39:45 +00005521 const Totals& totals,
Phil Nash89d1e6c2011-05-24 08:23:02 +01005522 const std::string& stdOut,
5523 const std::string& stdErr
5524 )
5525 {
5526 if( !stdOut.empty() )
5527 {
5528 StartSpansLazily();
5529 streamVariableLengthText( "stdout", stdOut );
5530 }
5531
5532 if( !stdErr.empty() )
5533 {
5534 StartSpansLazily();
5535 streamVariableLengthText( "stderr", stdErr );
5536 }
5537
5538 if( m_testSpan.emitted )
5539 {
Phil Nash918046a2012-02-28 20:04:42 +00005540 m_config.stream() << "[Finished: '" << testInfo.getName() << "' ";
Phil Nashf7299fc2012-02-25 09:39:45 +00005541 ReportCounts( totals );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005542 m_config.stream() << "]" << std::endl;
5543 }
5544 }
5545
5546 private: // helpers
5547
5548 ///////////////////////////////////////////////////////////////////////////
5549 void StartSpansLazily()
5550 {
5551 if( !m_testingSpan.emitted )
5552 {
5553 if( m_config.getName().empty() )
5554 m_config.stream() << "[Started testing]" << std::endl;
5555 else
5556 m_config.stream() << "[Started testing: " << m_config.getName() << "]" << std::endl;
5557 m_testingSpan.emitted = true;
5558 }
5559
5560 if( !m_groupSpan.emitted && !m_groupSpan.name.empty() )
5561 {
5562 m_config.stream() << "[Started group: '" << m_groupSpan.name << "']" << std::endl;
5563 m_groupSpan.emitted = true;
5564 }
5565
5566 if( !m_testSpan.emitted )
5567 {
5568 m_config.stream() << std::endl << "[Running: " << m_testSpan.name << "]" << std::endl;
5569 m_testSpan.emitted = true;
5570 }
5571
5572 if( !m_sectionSpans.empty() )
5573 {
5574 SpanInfo& sectionSpan = m_sectionSpans.back();
5575 if( !sectionSpan.emitted && !sectionSpan.name.empty() )
5576 {
5577 if( m_firstSectionInTestCase )
5578 {
5579 m_config.stream() << "\n";
5580 m_firstSectionInTestCase = false;
5581 }
5582 std::vector<SpanInfo>::iterator it = m_sectionSpans.begin();
5583 std::vector<SpanInfo>::iterator itEnd = m_sectionSpans.end();
5584 for(; it != itEnd; ++it )
5585 {
5586 SpanInfo& prevSpan = *it;
5587 if( !prevSpan.emitted && !prevSpan.name.empty() )
5588 {
5589 m_config.stream() << "[Started section: '" << prevSpan.name << "']" << std::endl;
5590 prevSpan.emitted = true;
5591 }
5592 }
5593 }
5594 }
5595 }
5596
5597 ///////////////////////////////////////////////////////////////////////////
5598 void streamVariableLengthText
5599 (
5600 const std::string& prefix,
5601 const std::string& text
5602 )
5603 {
5604 std::string trimmed = trim( text );
5605 if( trimmed.find_first_of( "\r\n" ) == std::string::npos )
5606 {
5607 m_config.stream() << "[" << prefix << ": " << trimmed << "]\n";
5608 }
5609 else
5610 {
Phil Nash918046a2012-02-28 20:04:42 +00005611 m_config.stream() << "\n[" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed
5612 << "\n[end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<<\n";
Phil Nash89d1e6c2011-05-24 08:23:02 +01005613 }
5614 }
5615
5616 private:
5617 const IReporterConfig& m_config;
5618 bool m_firstSectionInTestCase;
5619
5620 SpanInfo m_testingSpan;
5621 SpanInfo m_groupSpan;
5622 SpanInfo m_testSpan;
5623 std::vector<SpanInfo> m_sectionSpans;
5624 };
5625
5626 INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
5627
5628} // end namespace Catch
5629
5630// #included from: reporters/catch_reporter_xml.hpp
5631
5632/*
5633 * catch_reporter_xml.hpp
5634 * Catch
5635 *
5636 * Created by Phil on 28/10/2010.
5637 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
5638 *
5639 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5640 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5641 *
5642 */
5643#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
5644
Phil Nashf721a962011-06-07 14:13:57 +01005645// #included from: ../internal/catch_xmlwriter.hpp
Phil Nash89d1e6c2011-05-24 08:23:02 +01005646
5647/*
5648 * catch_xmlwriter.hpp
5649 * Catch
5650 *
5651 * Created by Phil on 09/12/2010.
5652 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
5653 *
5654 * Distributed under the Boost Software License, Version 1.0. (See accompanying
5655 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5656 */
5657#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
5658
5659#include <sstream>
5660#include <string>
5661#include <vector>
5662
5663namespace Catch
5664{
5665 class XmlWriter
5666 {
5667 public:
5668
5669 class ScopedElement
5670 {
5671 public:
5672 ///////////////////////////////////////////////////////////////////
5673 ScopedElement
5674 (
5675 XmlWriter* writer
5676 )
5677 : m_writer( writer )
5678 {
5679 }
5680
5681 ///////////////////////////////////////////////////////////////////
5682 ScopedElement
5683 (
5684 const ScopedElement& other
5685 )
5686 : m_writer( other.m_writer )
5687 {
5688 other.m_writer = NULL;
5689 }
5690
5691 ///////////////////////////////////////////////////////////////////
5692 ~ScopedElement
5693 ()
5694 {
5695 if( m_writer )
5696 m_writer->endElement();
5697 }
5698
5699 ///////////////////////////////////////////////////////////////////
5700 ScopedElement& writeText
5701 (
5702 const std::string& text
5703 )
5704 {
5705 m_writer->writeText( text );
5706 return *this;
5707 }
5708
5709 ///////////////////////////////////////////////////////////////////
5710 template<typename T>
5711 ScopedElement& writeAttribute
5712 (
5713 const std::string& name,
5714 const T& attribute
5715 )
5716 {
5717 m_writer->writeAttribute( name, attribute );
5718 return *this;
5719 }
5720
5721 private:
5722 mutable XmlWriter* m_writer;
5723 };
5724
5725 ///////////////////////////////////////////////////////////////////////
5726 XmlWriter
5727 ()
5728 : m_tagIsOpen( false ),
5729 m_needsNewline( false ),
5730 m_os( &std::cout )
5731 {
5732 }
5733
5734 ///////////////////////////////////////////////////////////////////////
5735 XmlWriter
5736 (
5737 std::ostream& os
5738 )
5739 : m_tagIsOpen( false ),
5740 m_needsNewline( false ),
5741 m_os( &os )
5742 {
5743 }
5744
5745 ///////////////////////////////////////////////////////////////////////
5746 ~XmlWriter
5747 ()
5748 {
5749 while( !m_tags.empty() )
5750 {
5751 endElement();
5752 }
5753 }
5754
5755 ///////////////////////////////////////////////////////////////////////
5756 XmlWriter& operator =
5757 (
5758 const XmlWriter& other
5759 )
5760 {
5761 XmlWriter temp( other );
5762 swap( temp );
5763 return *this;
5764 }
5765
5766 ///////////////////////////////////////////////////////////////////////
5767 void swap
5768 (
5769 XmlWriter& other
5770 )
5771 {
5772 std::swap( m_tagIsOpen, other.m_tagIsOpen );
5773 std::swap( m_needsNewline, other.m_needsNewline );
5774 std::swap( m_tags, other.m_tags );
5775 std::swap( m_indent, other.m_indent );
5776 std::swap( m_os, other.m_os );
5777 }
5778
5779 ///////////////////////////////////////////////////////////////////////
5780 XmlWriter& startElement
5781 (
5782 const std::string& name
5783 )
5784 {
5785 ensureTagClosed();
5786 newlineIfNecessary();
5787 stream() << m_indent << "<" << name;
5788 m_tags.push_back( name );
5789 m_indent += " ";
5790 m_tagIsOpen = true;
5791 return *this;
5792 }
5793
5794 ///////////////////////////////////////////////////////////////////////
5795 ScopedElement scopedElement
5796 (
5797 const std::string& name
5798 )
5799 {
5800 ScopedElement scoped( this );
5801 startElement( name );
5802 return scoped;
5803 }
5804
5805 ///////////////////////////////////////////////////////////////////////
5806 XmlWriter& endElement
5807 ()
5808 {
5809 newlineIfNecessary();
5810 m_indent = m_indent.substr( 0, m_indent.size()-2 );
5811 if( m_tagIsOpen )
5812 {
5813 stream() << "/>\n";
5814 m_tagIsOpen = false;
5815 }
5816 else
5817 {
5818 stream() << m_indent << "</" << m_tags.back() << ">\n";
5819 }
5820 m_tags.pop_back();
5821 return *this;
5822 }
5823
5824 ///////////////////////////////////////////////////////////////////////
5825 XmlWriter& writeAttribute
5826 (
5827 const std::string& name,
5828 const std::string& attribute
5829 )
5830 {
5831 if( !name.empty() && !attribute.empty() )
5832 {
5833 stream() << " " << name << "=\"";
5834 writeEncodedText( attribute );
5835 stream() << "\"";
5836 }
5837 return *this;
5838 }
5839
5840 ///////////////////////////////////////////////////////////////////////
5841 XmlWriter& writeAttribute
5842 (
5843 const std::string& name,
5844 bool attribute
5845 )
5846 {
5847 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
5848 return *this;
5849 }
5850
5851 ///////////////////////////////////////////////////////////////////////
5852 template<typename T>
5853 XmlWriter& writeAttribute
5854 (
5855 const std::string& name,
5856 const T& attribute
5857 )
5858 {
5859 if( !name.empty() )
5860 {
5861 stream() << " " << name << "=\"" << attribute << "\"";
5862 }
5863 return *this;
5864 }
5865
5866 ///////////////////////////////////////////////////////////////////////
5867 XmlWriter& writeText
5868 (
5869 const std::string& text
5870 )
5871 {
5872 if( !text.empty() )
5873 {
5874 bool tagWasOpen = m_tagIsOpen;
5875 ensureTagClosed();
5876 if( tagWasOpen )
5877 stream() << m_indent;
5878 writeEncodedText( text );
5879 m_needsNewline = true;
5880 }
5881 return *this;
5882 }
5883
5884 ///////////////////////////////////////////////////////////////////////
5885 XmlWriter& writeComment
5886 (
5887 const std::string& text
5888 )
5889 {
5890 ensureTagClosed();
5891 stream() << m_indent << "<!--" << text << "-->";
5892 m_needsNewline = true;
5893 return *this;
5894 }
5895
5896 ///////////////////////////////////////////////////////////////////////
5897 XmlWriter& writeBlankLine
5898 ()
5899 {
5900 ensureTagClosed();
5901 stream() << "\n";
5902 return *this;
5903 }
5904
5905 private:
5906
5907 ///////////////////////////////////////////////////////////////////////
5908 std::ostream& stream
5909 ()
5910 {
5911 return *m_os;
5912 }
5913
5914 ///////////////////////////////////////////////////////////////////////
5915 void ensureTagClosed
5916 ()
5917 {
5918 if( m_tagIsOpen )
5919 {
5920 stream() << ">\n";
5921 m_tagIsOpen = false;
5922 }
5923 }
5924
5925 ///////////////////////////////////////////////////////////////////////
5926 void newlineIfNecessary
5927 ()
5928 {
5929 if( m_needsNewline )
5930 {
5931 stream() << "\n";
5932 m_needsNewline = false;
5933 }
5934 }
5935
5936 ///////////////////////////////////////////////////////////////////////
5937 void writeEncodedText
5938 (
5939 const std::string& text
5940 )
5941 {
Phil Nash6e0f58d2012-02-15 18:37:21 +00005942 static const char* charsToEncode = "<&\"";
5943 std::string mtext = text;
5944 std::string::size_type pos = mtext.find_first_of( charsToEncode );
5945 while( pos != std::string::npos )
Phil Nash89d1e6c2011-05-24 08:23:02 +01005946 {
Phil Nash6e0f58d2012-02-15 18:37:21 +00005947 stream() << mtext.substr( 0, pos );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005948
Phil Nash6e0f58d2012-02-15 18:37:21 +00005949 switch( mtext[pos] )
5950 {
5951 case '<':
5952 stream() << "&lt;";
5953 break;
5954 case '&':
5955 stream() << "&amp;";
5956 break;
5957 case '\"':
5958 stream() << "&quot;";
5959 break;
5960 }
5961 mtext = mtext.substr( pos+1 );
5962 pos = mtext.find_first_of( charsToEncode );
Phil Nash89d1e6c2011-05-24 08:23:02 +01005963 }
Phil Nash6e0f58d2012-02-15 18:37:21 +00005964 stream() << mtext;
Phil Nash89d1e6c2011-05-24 08:23:02 +01005965 }
5966
5967 bool m_tagIsOpen;
5968 bool m_needsNewline;
5969 std::vector<std::string> m_tags;
5970 std::string m_indent;
5971 std::ostream* m_os;
5972 };
5973
5974}
5975
5976namespace Catch
5977{
5978 class XmlReporter : public Catch::IReporter
5979 {
5980 public:
5981 ///////////////////////////////////////////////////////////////////////////
5982 XmlReporter
5983 (
5984 const IReporterConfig& config
5985 )
5986 : m_config( config )
5987 {
5988 }
5989
5990 ///////////////////////////////////////////////////////////////////////////
5991 static std::string getDescription
5992 ()
5993 {
5994 return "Reports test results as an XML document";
5995 }
5996
5997 private: // IReporter
5998
5999 ///////////////////////////////////////////////////////////////////////////
Phil Nash333e6e62012-02-17 19:50:59 +00006000 virtual bool shouldRedirectStdout
6001 ()
6002 const
6003 {
6004 return true;
6005 }
6006
6007 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01006008 virtual void StartTesting
6009 ()
6010 {
6011 m_xml = XmlWriter( m_config.stream() );
6012 m_xml.startElement( "Catch" );
6013 if( !m_config.getName().empty() )
6014 m_xml.writeAttribute( "name", m_config.getName() );
6015 }
6016
6017 ///////////////////////////////////////////////////////////////////////////
6018 virtual void EndTesting
6019 (
Phil Nashf7299fc2012-02-25 09:39:45 +00006020 const Totals& totals
Phil Nash89d1e6c2011-05-24 08:23:02 +01006021 )
6022 {
6023 m_xml.scopedElement( "OverallResults" )
Phil Nashf7299fc2012-02-25 09:39:45 +00006024 .writeAttribute( "successes", totals.assertions.passed )
6025 .writeAttribute( "failures", totals.assertions.failed );
Phil Nash89d1e6c2011-05-24 08:23:02 +01006026 m_xml.endElement();
6027 }
6028
6029 ///////////////////////////////////////////////////////////////////////////
6030 virtual void StartGroup
6031 (
6032 const std::string& groupName
6033 )
6034 {
6035 m_xml.startElement( "Group" )
6036 .writeAttribute( "name", groupName );
6037 }
6038
6039 ///////////////////////////////////////////////////////////////////////////
6040 virtual void EndGroup
6041 (
6042 const std::string& /*groupName*/,
Phil Nashf7299fc2012-02-25 09:39:45 +00006043 const Totals& totals
Phil Nash89d1e6c2011-05-24 08:23:02 +01006044 )
6045 {
6046 m_xml.scopedElement( "OverallResults" )
Phil Nashf7299fc2012-02-25 09:39:45 +00006047 .writeAttribute( "successes", totals.assertions.passed )
6048 .writeAttribute( "failures", totals.assertions.failed );
Phil Nash89d1e6c2011-05-24 08:23:02 +01006049 m_xml.endElement();
6050 }
6051
6052 ///////////////////////////////////////////////////////////////////////////
6053 virtual void StartSection( const std::string& sectionName, const std::string description )
6054 {
6055 m_xml.startElement( "Section" )
6056 .writeAttribute( "name", sectionName )
6057 .writeAttribute( "description", description );
6058 }
6059
6060 ///////////////////////////////////////////////////////////////////////////
Phil Nashf7299fc2012-02-25 09:39:45 +00006061 virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006062 {
6063 m_xml.scopedElement( "OverallResults" )
Phil Nashf7299fc2012-02-25 09:39:45 +00006064 .writeAttribute( "successes", assertions.passed )
6065 .writeAttribute( "failures", assertions.failed );
Phil Nash89d1e6c2011-05-24 08:23:02 +01006066 m_xml.endElement();
6067 }
6068
6069 ///////////////////////////////////////////////////////////////////////////
6070 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo )
6071 {
6072 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.getName() );
6073 m_currentTestSuccess = true;
6074 }
6075
6076 ///////////////////////////////////////////////////////////////////////////
6077 virtual void Result( const Catch::ResultInfo& resultInfo )
6078 {
6079 if( !m_config.includeSuccessfulResults() && resultInfo.getResultType() == ResultWas::Ok )
6080 return;
6081
6082 if( resultInfo.hasExpression() )
6083 {
6084 m_xml.startElement( "Expression" )
6085 .writeAttribute( "success", resultInfo.ok() )
6086 .writeAttribute( "filename", resultInfo.getFilename() )
6087 .writeAttribute( "line", resultInfo.getLine() );
6088
6089 m_xml.scopedElement( "Original" )
6090 .writeText( resultInfo.getExpression() );
6091 m_xml.scopedElement( "Expanded" )
6092 .writeText( resultInfo.getExpandedExpression() );
6093 m_currentTestSuccess &= resultInfo.ok();
6094 }
6095
6096 switch( resultInfo.getResultType() )
6097 {
6098 case ResultWas::ThrewException:
6099 m_xml.scopedElement( "Exception" )
6100 .writeAttribute( "filename", resultInfo.getFilename() )
6101 .writeAttribute( "line", resultInfo.getLine() )
6102 .writeText( resultInfo.getMessage() );
6103 m_currentTestSuccess = false;
6104 break;
6105 case ResultWas::Info:
6106 m_xml.scopedElement( "Info" )
6107 .writeText( resultInfo.getMessage() );
6108 break;
6109 case ResultWas::Warning:
6110 m_xml.scopedElement( "Warning" )
6111 .writeText( resultInfo.getMessage() );
6112 break;
6113 case ResultWas::ExplicitFailure:
6114 m_xml.scopedElement( "Failure" )
6115 .writeText( resultInfo.getMessage() );
6116 m_currentTestSuccess = false;
6117 break;
Phil Nashf51d3162011-12-28 10:37:31 +00006118 case ResultWas::Unknown:
6119 case ResultWas::Ok:
6120 case ResultWas::FailureBit:
6121 case ResultWas::ExpressionFailed:
6122 case ResultWas::Exception:
6123 case ResultWas::DidntThrowException:
Phil Nash89d1e6c2011-05-24 08:23:02 +01006124 default:
6125 break;
6126 }
6127 if( resultInfo.hasExpression() )
6128 m_xml.endElement();
6129 }
6130
6131 ///////////////////////////////////////////////////////////////////////////
Phil Nashf7299fc2012-02-25 09:39:45 +00006132 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals& /* totals */, const std::string& /*stdOut*/, const std::string& /*stdErr*/ )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006133 {
6134 m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess );
6135 m_xml.endElement();
6136 }
6137
6138 private:
6139 const IReporterConfig& m_config;
6140 bool m_currentTestSuccess;
6141 XmlWriter m_xml;
6142 };
6143
6144 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
6145
6146} // end namespace Catch
6147
6148// #included from: reporters/catch_reporter_junit.hpp
6149
6150/*
6151 * catch_reporter_junit.hpp
6152 * Catch
6153 *
6154 * Created by Phil on 26/11/2010.
6155 * Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
6156 *
6157 * Distributed under the Boost Software License, Version 1.0. (See accompanying
6158 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6159 *
6160 */
6161#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
6162
6163
6164namespace Catch
6165{
6166 class JunitReporter : public Catch::IReporter
6167 {
6168 struct TestStats
6169 {
6170 std::string m_element;
6171 std::string m_resultType;
6172 std::string m_message;
6173 std::string m_content;
6174 };
6175
6176 struct TestCaseStats
6177 {
6178 TestCaseStats( const std::string& name = std::string() )
6179 : m_name( name )
6180 {
6181 }
6182
6183 double m_timeInSeconds;
6184 std::string m_status;
6185 std::string m_className;
6186 std::string m_name;
6187 std::vector<TestStats> m_testStats;
6188 };
6189
6190 struct Stats
6191 {
6192 Stats( const std::string& name = std::string() )
6193 : m_testsCount( 0 ),
6194 m_failuresCount( 0 ),
6195 m_disabledCount( 0 ),
6196 m_errorsCount( 0 ),
6197 m_timeInSeconds( 0 ),
6198 m_name( name )
6199 {
6200 }
6201
6202 std::size_t m_testsCount;
6203 std::size_t m_failuresCount;
6204 std::size_t m_disabledCount;
6205 std::size_t m_errorsCount;
6206 double m_timeInSeconds;
6207 std::string m_name;
6208
6209 std::vector<TestCaseStats> m_testCaseStats;
6210 };
6211
6212 public:
6213 ///////////////////////////////////////////////////////////////////////////
6214 JunitReporter( const IReporterConfig& config )
6215 : m_config( config ),
6216 m_testSuiteStats( "AllTests" ),
6217 m_currentStats( &m_testSuiteStats )
6218 {
6219 }
6220
6221 ///////////////////////////////////////////////////////////////////////////
6222 static std::string getDescription()
6223 {
6224 return "Reports test results in an XML format that looks like Ant's junitreport target";
6225 }
6226
6227 private: // IReporter
6228
6229 ///////////////////////////////////////////////////////////////////////////
Phil Nash333e6e62012-02-17 19:50:59 +00006230 virtual bool shouldRedirectStdout
6231 ()
6232 const
6233 {
6234 return true;
6235 }
6236
6237 ///////////////////////////////////////////////////////////////////////////
Phil Nash89d1e6c2011-05-24 08:23:02 +01006238 virtual void StartTesting()
6239 {
6240 }
6241
6242 ///////////////////////////////////////////////////////////////////////////
6243 virtual void StartGroup( const std::string& groupName )
6244 {
6245
6246 m_statsForSuites.push_back( Stats( groupName ) );
6247 m_currentStats = &m_statsForSuites.back();
6248 }
6249
6250 ///////////////////////////////////////////////////////////////////////////
Phil Nashf7299fc2012-02-25 09:39:45 +00006251 virtual void EndGroup( const std::string&, const Totals& totals )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006252 {
Phil Nashf7299fc2012-02-25 09:39:45 +00006253 m_currentStats->m_testsCount = totals.assertions.total();
Phil Nash89d1e6c2011-05-24 08:23:02 +01006254 m_currentStats = &m_testSuiteStats;
6255 }
6256
6257 virtual void StartSection( const std::string& /*sectionName*/, const std::string /*description*/ )
6258 {
6259 }
6260
Phil Nashf7299fc2012-02-25 09:39:45 +00006261 virtual void EndSection( const std::string& /*sectionName*/, const Counts& /* assertions */ )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006262 {
6263 }
6264
6265 ///////////////////////////////////////////////////////////////////////////
6266 virtual void StartTestCase( const Catch::TestCaseInfo& testInfo )
6267 {
6268 m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getName() ) );
6269
6270 }
6271
6272 ///////////////////////////////////////////////////////////////////////////
6273 virtual void Result( const Catch::ResultInfo& resultInfo )
6274 {
6275 if( resultInfo.getResultType() != ResultWas::Ok || m_config.includeSuccessfulResults() )
6276 {
6277 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back();
6278 TestStats stats;
6279 std::ostringstream oss;
6280 if( !resultInfo.getMessage().empty() )
6281 {
6282 oss << resultInfo.getMessage() << " at ";
6283 }
Phil Nash6e0f58d2012-02-15 18:37:21 +00006284 oss << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
Phil Nash89d1e6c2011-05-24 08:23:02 +01006285 stats.m_content = oss.str();
6286 stats.m_message = resultInfo.getExpandedExpression();
6287 stats.m_resultType = resultInfo.getTestMacroName();
6288 switch( resultInfo.getResultType() )
6289 {
6290 case ResultWas::ThrewException:
6291 stats.m_element = "error";
6292 m_currentStats->m_errorsCount++;
6293 break;
6294 case ResultWas::Info:
6295 stats.m_element = "info"; // !TBD ?
6296 break;
6297 case ResultWas::Warning:
6298 stats.m_element = "warning"; // !TBD ?
6299 break;
6300 case ResultWas::ExplicitFailure:
6301 stats.m_element = "failure";
6302 m_currentStats->m_failuresCount++;
6303 break;
6304 case ResultWas::ExpressionFailed:
6305 stats.m_element = "failure";
6306 m_currentStats->m_failuresCount++;
6307 break;
6308 case ResultWas::Ok:
6309 stats.m_element = "success";
6310 break;
Phil Nashf51d3162011-12-28 10:37:31 +00006311 case ResultWas::Unknown:
6312 case ResultWas::FailureBit:
6313 case ResultWas::Exception:
6314 case ResultWas::DidntThrowException:
Phil Nash89d1e6c2011-05-24 08:23:02 +01006315 default:
6316 stats.m_element = "unknown";
6317 break;
6318 }
6319 testCaseStats.m_testStats.push_back( stats );
6320
6321 }
6322 }
6323
6324 ///////////////////////////////////////////////////////////////////////////
Phil Nashf7299fc2012-02-25 09:39:45 +00006325 virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals& /* totals */, const std::string& stdOut, const std::string& stdErr )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006326 {
6327 if( !stdOut.empty() )
6328 m_stdOut << stdOut << "\n";
6329 if( !stdErr.empty() )
6330 m_stdErr << stdErr << "\n";
6331 }
6332
6333 ///////////////////////////////////////////////////////////////////////////
Phil Nashf7299fc2012-02-25 09:39:45 +00006334 virtual void EndTesting( const Totals& /* totals */ )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006335 {
6336 std::ostream& str = m_config.stream();
6337 {
6338 XmlWriter xml( str );
6339
6340 if( m_statsForSuites.size() > 0 )
6341 xml.startElement( "testsuites" );
6342
6343 std::vector<Stats>::const_iterator it = m_statsForSuites.begin();
6344 std::vector<Stats>::const_iterator itEnd = m_statsForSuites.end();
6345
6346 for(; it != itEnd; ++it )
6347 {
6348 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
6349 xml.writeAttribute( "name", it->m_name );
6350 xml.writeAttribute( "errors", it->m_errorsCount );
6351 xml.writeAttribute( "failures", it->m_failuresCount );
6352 xml.writeAttribute( "tests", it->m_testsCount );
6353 xml.writeAttribute( "hostname", "tbd" );
6354 xml.writeAttribute( "time", "tbd" );
6355 xml.writeAttribute( "timestamp", "tbd" );
6356
6357 OutputTestCases( xml, *it );
6358 }
6359
6360 xml.scopedElement( "system-out" ).writeText( trim( m_stdOut.str() ) );
6361 xml.scopedElement( "system-err" ).writeText( trim( m_stdOut.str() ) );
6362 }
6363 }
6364
6365 ///////////////////////////////////////////////////////////////////////////
6366 void OutputTestCases( XmlWriter& xml, const Stats& stats )
6367 {
6368 std::vector<TestCaseStats>::const_iterator it = stats.m_testCaseStats.begin();
6369 std::vector<TestCaseStats>::const_iterator itEnd = stats.m_testCaseStats.end();
6370 for(; it != itEnd; ++it )
6371 {
6372 xml.writeBlankLine();
6373 xml.writeComment( "Test case" );
6374
6375 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
6376 xml.writeAttribute( "classname", it->m_className );
6377 xml.writeAttribute( "name", it->m_name );
6378 xml.writeAttribute( "time", "tbd" );
6379
6380 OutputTestResult( xml, *it );
6381 }
6382 }
6383
6384
6385 ///////////////////////////////////////////////////////////////////////////
6386 void OutputTestResult( XmlWriter& xml, const TestCaseStats& stats )
6387 {
6388 std::vector<TestStats>::const_iterator it = stats.m_testStats.begin();
6389 std::vector<TestStats>::const_iterator itEnd = stats.m_testStats.end();
6390 for(; it != itEnd; ++it )
6391 {
6392 if( it->m_element != "success" )
6393 {
6394 XmlWriter::ScopedElement e = xml.scopedElement( it->m_element );
6395
6396 xml.writeAttribute( "message", it->m_message );
6397 xml.writeAttribute( "type", it->m_resultType );
6398 if( !it->m_content.empty() )
6399 xml.writeText( it->m_content );
6400 }
6401 }
6402 }
6403
6404 private:
6405 const IReporterConfig& m_config;
6406 bool m_currentTestSuccess;
6407
6408 Stats m_testSuiteStats;
6409 Stats* m_currentStats;
6410 std::vector<Stats> m_statsForSuites;
6411 std::ostringstream m_stdOut;
6412 std::ostringstream m_stdErr;
6413 };
6414
6415 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
6416
6417} // end namespace Catch
6418
6419
6420#include <fstream>
6421#include <stdlib.h>
6422#include <limits>
6423
6424namespace Catch
6425{
6426 //////////////////////////////////////////////////////////////////////////
6427 inline int Main
6428 (
6429 Config& config
6430 )
6431 {
6432 // Handle list request
6433 if( config.listWhat() != Config::List::None )
6434 return List( config );
6435
6436 // Open output file, if specified
6437 std::ofstream ofs;
6438 if( !config.getFilename().empty() )
6439 {
6440 ofs.open( config.getFilename().c_str() );
6441 if( ofs.fail() )
6442 {
6443 std::cerr << "Unable to open file: '" << config.getFilename() << "'" << std::endl;
6444 return (std::numeric_limits<int>::max)();
6445 }
6446 config.setStreamBuf( ofs.rdbuf() );
6447 }
6448
6449 Runner runner( config );
6450
6451 // Run test specs specified on the command line - or default to all
6452 if( !config.testsSpecified() )
6453 {
6454 config.getReporter()->StartGroup( "" );
6455 runner.runAll();
Phil Nashf7299fc2012-02-25 09:39:45 +00006456 config.getReporter()->EndGroup( "", runner.getTotals() );
Phil Nash89d1e6c2011-05-24 08:23:02 +01006457 }
6458 else
6459 {
6460 // !TBD We should get all the testcases upfront, report any missing,
6461 // then just run them
6462 std::vector<std::string>::const_iterator it = config.getTestSpecs().begin();
6463 std::vector<std::string>::const_iterator itEnd = config.getTestSpecs().end();
6464 for(; it != itEnd; ++it )
6465 {
Phil Nashf7299fc2012-02-25 09:39:45 +00006466 Totals prevTotals = runner.getTotals();
Phil Nash89d1e6c2011-05-24 08:23:02 +01006467 config.getReporter()->StartGroup( *it );
6468 if( runner.runMatching( *it ) == 0 )
6469 {
6470 // Use reporter?
6471// std::cerr << "\n[Unable to match any test cases with: " << *it << "]" << std::endl;
6472 }
Phil Nashf7299fc2012-02-25 09:39:45 +00006473 config.getReporter()->EndGroup( *it, runner.getTotals() - prevTotals );
Phil Nash89d1e6c2011-05-24 08:23:02 +01006474 }
6475 }
Phil Nash6e0f58d2012-02-15 18:37:21 +00006476
Phil Nashf7299fc2012-02-25 09:39:45 +00006477 return static_cast<int>( runner.getTotals().assertions.failed );
Phil Nash89d1e6c2011-05-24 08:23:02 +01006478 }
6479
6480 //////////////////////////////////////////////////////////////////////////
Phil Nashf51d3162011-12-28 10:37:31 +00006481 inline void showHelp
Phil Nash89d1e6c2011-05-24 08:23:02 +01006482 (
6483 std::string exeName
6484 )
6485 {
6486 std::string::size_type pos = exeName.find_last_of( "/\\" );
6487 if( pos != std::string::npos )
6488 {
6489 exeName = exeName.substr( pos+1 );
6490 }
6491
6492 std::cout << exeName << " is a CATCH host application. Options are as follows:\n\n"
6493 << "\t-l, --list <tests | reporters> [xml]\n"
6494 << "\t-t, --test <testspec> [<testspec>...]\n"
6495 << "\t-r, --reporter <reporter name>\n"
6496 << "\t-o, --out <file name>|<%stream name>\n"
6497 << "\t-s, --success\n"
6498 << "\t-b, --break\n"
6499 << "\t-n, --name <name>\n\n"
6500 << "For more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line" << std::endl;
6501 }
6502
6503 //////////////////////////////////////////////////////////////////////////
6504 inline int Main
6505 (
6506 int argc,
6507 char* const argv[],
6508 Config& config
6509 )
6510 {
6511 ArgParser( argc, argv, config );
6512
6513 if( !config.getMessage().empty() )
6514 {
6515 std::cerr << config.getMessage() << std::endl;
6516 return (std::numeric_limits<int>::max)();
6517 }
6518
6519 // Handle help
6520 if( config.showHelp() )
6521 {
6522 showHelp( argv[0] );
6523 return 0;
6524 }
6525
6526 return Main( config );
6527 }
6528
6529 //////////////////////////////////////////////////////////////////////////
6530 inline int Main
6531 (
6532 int argc,
6533 char* const argv[]
6534 )
6535 {
6536 Config config;
6537// if( isDebuggerActive() )
6538// config.useStream( "debug" );
6539 return Main( argc, argv, config );
6540 }
6541
6542} // end namespace Catch
6543
6544#endif
6545
6546#ifdef CATCH_CONFIG_MAIN
6547// #included from: internal/catch_default_main.hpp
6548
6549/*
6550 * catch_default_main.hpp
6551 * Catch
6552 *
6553 * Created by Phil on 20/05/2011.
6554 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
6555 *
6556 * Distributed under the Boost Software License, Version 1.0. (See accompanying
6557 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6558 *
6559 */
6560
6561#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
6562
6563int main (int argc, char * const argv[])
6564{
6565#ifdef __OBJC__
6566
6567 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
6568
6569 Catch::registerTestMethods();
6570
6571 int result = Catch::Main( argc, (char* const*)argv );
6572
6573 [pool drain];
Phil Nash89d1e6c2011-05-24 08:23:02 +01006574
6575#else
6576
Phil Nashdd5b9c22012-02-18 09:58:30 +00006577 int result =Catch::Main( argc, argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +01006578
6579#endif
Phil Nashdd5b9c22012-02-18 09:58:30 +00006580 Catch::Hub::cleanUp();
6581 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +01006582}
6583
Phil Nash89d1e6c2011-05-24 08:23:02 +01006584#endif
6585
Phil Nash89d1e6c2011-05-24 08:23:02 +01006586//////
6587
6588#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "REQUIRE" )
6589#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "REQUIRE_FALSE" )
6590
6591#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "REQUIRE_THROWS" )
6592#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "REQUIRE_THROWS_AS" )
6593#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "REQUIRE_NOTHROW" )
6594
6595#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CHECK" )
6596#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CHECK_FALSE" )
Phil Nasha162e222012-02-10 08:30:13 +00006597#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CHECKED_IF" )
6598#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CHECKED_ELSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +01006599
6600#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CHECK_THROWS" )
6601#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" )
6602#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CHECK_NOTHROW" )
6603
6604#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" )
6605#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" )
6606#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
6607#define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
6608#define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CAPTURE" )
6609
6610#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
6611
6612#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
6613#define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
6614#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
6615#define METHOD_AS_TEST_CASE( method, name, description ) CATCH_METHOD_AS_TEST_CASE( method, name, description )
6616
6617#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
6618#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
6619
6620#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
6621
6622///////////////
6623// Still to be implemented
6624#define CHECK_NOFAIL( expr ) // !TBD - reports violation, but doesn't fail Test
6625
6626using Catch::Detail::Approx;
6627
6628#endif // TWOBLUECUBES_CATCH_HPP_INCLUDED
6629