| 
									
										
										
										
											2011-01-14 08:38:46 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *  Created by Phil on 14/01/2011. | 
					
						
							|  |  |  |  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | 
					
						
							|  |  |  |  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #ifndef TWOBLUECUBES_CATCH_SELF_TEST_HPP_INCLUDED
 | 
					
						
							|  |  |  | #define TWOBLUECUBES_CATCH_SELF_TEST_HPP_INCLUDED
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-24 08:23:02 +01:00
										 |  |  | #include "catch.hpp"
 | 
					
						
							| 
									
										
										
										
											2011-01-14 08:38:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  | #include "set"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  | namespace Catch { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |     class MockReporter : public SharedImpl<IReporter> { | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |     public: | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         static const std::string recordGroups; | 
					
						
							|  |  |  |         static const std::string recordTestCases; | 
					
						
							|  |  |  |         static const std::string recordSections; | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         void recordAll() { | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |             addRecorder( recordGroups ); | 
					
						
							|  |  |  |             addRecorder( recordTestCases ); | 
					
						
							|  |  |  |             addRecorder( recordSections ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |                  | 
					
						
							| 
									
										
										
										
											2012-05-24 08:23:55 +01:00
										 |  |  |         MockReporter( const IReporterConfig& ) { | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |             recordAll(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         MockReporter() { | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |             recordAll(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         void addRecorder( const std::string& recorder ) { | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |             m_recorders.insert( recorder ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         static std::string getDescription() { | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |             return "mock reporter"; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         std::string getLog() const { | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |             return m_log.str(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |     private: // IReporter
 | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         virtual bool shouldRedirectStdout() const { | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         virtual void StartTesting() {} | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-24 08:23:55 +01:00
										 |  |  |         virtual void EndTesting( const Totals& ) {} | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         virtual void StartGroup( const std::string& groupName ) { | 
					
						
							| 
									
										
										
										
											2012-05-05 19:32:52 +01:00
										 |  |  |             openLabel( recordGroups, groupName ); | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-24 08:23:55 +01:00
										 |  |  |         virtual void EndGroup( const std::string& groupName, const Totals& ) { | 
					
						
							| 
									
										
										
										
											2012-05-05 19:32:52 +01:00
										 |  |  |             closeLabel( recordGroups, groupName ); | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-24 08:23:55 +01:00
										 |  |  |         virtual void StartSection( const std::string& sectionName, const std::string& ) { | 
					
						
							| 
									
										
										
										
											2012-05-05 19:32:52 +01:00
										 |  |  |             openLabel( recordSections, sectionName ); | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-24 08:23:55 +01:00
										 |  |  |         virtual void EndSection( const std::string& sectionName, const Counts& ) { | 
					
						
							| 
									
										
										
										
											2012-05-05 19:32:52 +01:00
										 |  |  |             closeLabel( recordSections, sectionName ); | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         virtual void StartTestCase( const TestCaseInfo& testInfo ) { | 
					
						
							| 
									
										
										
										
											2012-05-05 19:32:52 +01:00
										 |  |  |             openLabel( recordTestCases, testInfo.getName()  ); | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         virtual void EndTestCase(   const TestCaseInfo& testInfo,  | 
					
						
							| 
									
										
										
										
											2012-05-24 08:23:55 +01:00
										 |  |  |                                     const Totals&, | 
					
						
							|  |  |  |                                     const std::string&,  | 
					
						
							|  |  |  |                                     const std::string& ) { | 
					
						
							| 
									
										
										
										
											2012-05-05 19:32:52 +01:00
										 |  |  |             closeLabel( recordTestCases, testInfo.getName()  ); | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         virtual void Result( const ResultInfo& resultInfo ); | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         bool shouldRecord( const std::string& recorder ) const { | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |             return m_recorders.find( recorder ) != m_recorders.end(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-05-05 19:32:52 +01:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-07 18:59:33 +01:00
										 |  |  |         void openLabel( const std::string& label, const std::string& arg = "" ); | 
					
						
							|  |  |  |         void closeLabel( const std::string& label, const std::string& arg = "" ); | 
					
						
							| 
									
										
										
										
											2012-05-05 19:32:52 +01:00
										 |  |  |          | 
					
						
							|  |  |  |         std::string m_indent; | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |         std::ostringstream m_log; | 
					
						
							|  |  |  |         std::set<std::string> m_recorders; | 
					
						
							|  |  |  |     };     | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |     class EmbeddedRunner { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 08:38:46 +00:00
										 |  |  |     public: | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         EmbeddedRunner() : m_reporter( new MockReporter() ) {} | 
					
						
							| 
									
										
										
										
											2011-01-14 08:38:46 +00:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         std::size_t runMatching(    const std::string& rawTestSpec, | 
					
						
							|  |  |  |                                     const std::string& reporter = "basic" ); | 
					
						
							| 
									
										
										
										
											2011-03-11 19:44:59 +00:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         std::string getOutput() { | 
					
						
							| 
									
										
										
										
											2011-02-09 09:08:10 +00:00
										 |  |  |             return m_output; | 
					
						
							| 
									
										
										
										
											2011-01-14 08:38:46 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         const Totals& getTotals() const { | 
					
						
							| 
									
										
										
										
											2012-02-23 18:51:21 +00:00
										 |  |  |             return m_totals; | 
					
						
							| 
									
										
										
										
											2011-01-14 08:38:46 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         void addRecorder( const std::string& recorder ) { | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |             m_reporter->addRecorder( recorder ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         std::string getLog() const { | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |             return m_reporter->getLog(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-01-14 08:38:46 +00:00
										 |  |  |          | 
					
						
							|  |  |  |     private: | 
					
						
							| 
									
										
										
										
											2012-02-23 18:51:21 +00:00
										 |  |  |         Totals m_totals; | 
					
						
							| 
									
										
										
										
											2011-02-09 09:08:10 +00:00
										 |  |  |         std::string m_output; | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |         Ptr<MockReporter> m_reporter; | 
					
						
							| 
									
										
										
										
											2011-01-14 08:38:46 +00:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2011-03-11 19:44:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |     class MetaTestRunner { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-11 19:44:59 +00:00
										 |  |  |     public: | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         struct Expected { enum Result { | 
					
						
							|  |  |  |             ToSucceed, | 
					
						
							|  |  |  |             ToFail | 
					
						
							|  |  |  |         }; }; | 
					
						
							| 
									
										
										
										
											2011-03-11 19:44:59 +00:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         MetaTestRunner( Expected::Result expectedResult ) : m_expectedResult( expectedResult ) {} | 
					
						
							| 
									
										
										
										
											2011-03-11 19:44:59 +00:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         static void runMatching(    const std::string& testSpec,  | 
					
						
							|  |  |  |                                     Expected::Result expectedResult ) { | 
					
						
							| 
									
										
										
										
											2012-05-21 18:52:09 +01:00
										 |  |  |             forEach(    getCurrentContext().getTestCaseRegistry().getMatchingTestCases( testSpec ),  | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |                         MetaTestRunner( expectedResult ) ); | 
					
						
							| 
									
										
										
										
											2011-03-11 19:44:59 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         void operator()( const TestCaseInfo& testCase ) { | 
					
						
							| 
									
										
										
										
											2011-03-11 19:44:59 +00:00
										 |  |  |             EmbeddedRunner runner; | 
					
						
							|  |  |  |             runner.runMatching( testCase.getName() ); | 
					
						
							| 
									
										
										
										
											2012-02-23 18:51:21 +00:00
										 |  |  |             Totals totals = runner.getTotals(); | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |             switch( m_expectedResult ) { | 
					
						
							| 
									
										
										
										
											2011-03-11 19:44:59 +00:00
										 |  |  |                 case Expected::ToSucceed: | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |                     if( totals.assertions.failed > 0 ) { | 
					
						
							| 
									
										
										
										
											2011-03-11 19:44:59 +00:00
										 |  |  |                         INFO( runner.getOutput() ); | 
					
						
							|  |  |  |                         FAIL( "Expected test case '"  | 
					
						
							|  |  |  |                              << testCase.getName()  | 
					
						
							|  |  |  |                              << "' to succeed but there was/ were "  | 
					
						
							| 
									
										
										
										
											2012-02-23 18:51:21 +00:00
										 |  |  |                              << totals.assertions.failed << " failure(s)" ); | 
					
						
							| 
									
										
										
										
											2011-03-11 19:44:59 +00:00
										 |  |  |                     } | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 case Expected::ToFail: | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |                     if( totals.assertions.passed > 0 ) { | 
					
						
							| 
									
										
										
										
											2011-03-11 19:44:59 +00:00
										 |  |  |                         INFO( runner.getOutput() ); | 
					
						
							|  |  |  |                         FAIL( "Expected test case '"  | 
					
						
							|  |  |  |                              << testCase.getName()  | 
					
						
							|  |  |  |                              << "' to fail but there was/ were "  | 
					
						
							| 
									
										
										
										
											2012-02-23 18:51:21 +00:00
										 |  |  |                              << totals.assertions.passed << " success(es)" ); | 
					
						
							| 
									
										
										
										
											2011-03-11 19:44:59 +00:00
										 |  |  |                     } | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |             }         | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  |         Expected::Result m_expectedResult; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2012-02-15 08:20:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |     struct LineInfoRegistry { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static LineInfoRegistry& get() { | 
					
						
							| 
									
										
										
										
											2012-02-15 08:20:06 +00:00
										 |  |  |             static LineInfoRegistry s_instance; | 
					
						
							|  |  |  |             return s_instance; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         void registerLineInfo(  const std::string& name,  | 
					
						
							|  |  |  |                                 const SourceLineInfo& info ) { | 
					
						
							| 
									
										
										
										
											2012-02-15 08:20:06 +00:00
										 |  |  |             m_registry.insert( std::make_pair( name, info ) ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         const SourceLineInfo* find( const std::string& name ) const { | 
					
						
							| 
									
										
										
										
											2012-02-15 08:20:06 +00:00
										 |  |  |             std::map<std::string, SourceLineInfo>::const_iterator it = m_registry.find( name ); | 
					
						
							|  |  |  |             return it == m_registry.end() ? NULL : &(it->second); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |         const std::string infoForName( const std::string& name ) const { | 
					
						
							| 
									
										
										
										
											2012-02-15 08:20:06 +00:00
										 |  |  |             std::map<std::string, SourceLineInfo>::const_iterator it = m_registry.find( name ); | 
					
						
							|  |  |  |             if( it == m_registry.end() ) | 
					
						
							|  |  |  |                 return ""; | 
					
						
							|  |  |  |             std::ostringstream oss; | 
					
						
							|  |  |  |             oss << it->second; | 
					
						
							|  |  |  |             return oss.str(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         std::map<std::string, SourceLineInfo> m_registry; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2012-05-16 15:02:51 +01:00
										 |  |  |     struct LineInfoRegistrar { | 
					
						
							|  |  |  |         LineInfoRegistrar( const char* name, const SourceLineInfo& lineInfo ) { | 
					
						
							| 
									
										
										
										
											2012-02-15 08:20:06 +00:00
										 |  |  |             LineInfoRegistry::get().registerLineInfo( name, lineInfo ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2012-05-04 07:55:11 +01:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2011-01-14 08:38:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-15 08:20:06 +00:00
										 |  |  | #define CATCH_REGISTER_LINE_INFO( name ) ::Catch::LineInfoRegistrar INTERNAL_CATCH_UNIQUE_NAME( lineRegistrar )( name, ::Catch::SourceLineInfo( __FILE__, __LINE__ ) );
 | 
					
						
							|  |  |  | #define CATCH_GET_LINE_INFO( name ) ::Catch::LineInfoRegistry::get().infoForName( name )
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 08:38:46 +00:00
										 |  |  | #endif // TWOBLUECUBES_CATCH_SELF_TEST_HPP_INCLUDED
 |