mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27:11 +01:00 
			
		
		
		
	Moved new test spec code into appropriate header
- about to remove old test spec code and rewire throughout the codebase!
This commit is contained in:
		| @@ -77,6 +77,10 @@ namespace Catch { | ||||
|     FreeFunctionTestCase::~FreeFunctionTestCase() {} | ||||
|     IGeneratorInfo::~IGeneratorInfo() {} | ||||
|     IGeneratorsForTest::~IGeneratorsForTest() {} | ||||
|     TestSpec::Pattern::~Pattern() {} | ||||
|     TestSpec::NamePattern::~NamePattern() {} | ||||
|     TestSpec::TagPattern::~TagPattern() {} | ||||
|     TestSpec::ExcludedPattern::~ExcludedPattern() {} | ||||
|  | ||||
|     Matchers::Impl::StdString::Equals::~Equals() {} | ||||
|     Matchers::Impl::StdString::Contains::~Contains() {} | ||||
|   | ||||
| @@ -8,13 +8,107 @@ | ||||
| #ifndef TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED | ||||
|  | ||||
| #include "catch_tags.h" | ||||
| #include "catch_test_case_info.h" | ||||
| #include "catch_tags.h" // deprecated | ||||
|  | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     class TestSpec { | ||||
|         struct Pattern : SharedImpl<> { | ||||
|             virtual ~Pattern(); | ||||
|             virtual bool matches( TestCaseInfo const& testCase ) const = 0; | ||||
|         }; | ||||
|         class NamePattern : public Pattern { | ||||
|             enum WildcardPosition { | ||||
|                 NoWildcard = 0, | ||||
|                 WildcardAtStart = 1, | ||||
|                 WildcardAtEnd = 2, | ||||
|                 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd | ||||
|             }; | ||||
|  | ||||
|         public: | ||||
|             NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { | ||||
|                 if( startsWith( m_name, "*" ) ) { | ||||
|                     m_name = name.substr( 1 ); | ||||
|                     m_wildcard = WildcardAtStart; | ||||
|                 } | ||||
|                 if( endsWith( m_name, "*" ) ) { | ||||
|                     m_name = m_name.substr( 0, m_name.size()-1 ); | ||||
|                     m_wildcard = (WildcardPosition)( m_wildcard | WildcardAtEnd ); | ||||
|                 } | ||||
|             } | ||||
|             virtual ~NamePattern(); | ||||
|             virtual bool matches( TestCaseInfo const& testCase ) const { | ||||
|                 switch( m_wildcard ) { | ||||
|                     case NoWildcard: | ||||
|                         return m_name == toLower( testCase.name ); | ||||
|                     case WildcardAtStart: | ||||
|                         return endsWith( toLower( testCase.name ), m_name ); | ||||
|                     case WildcardAtEnd: | ||||
|                         return startsWith( toLower( testCase.name ), m_name ); | ||||
|                     case WildcardAtBothEnds: | ||||
|                         return contains( toLower( testCase.name ), m_name ); | ||||
|                 } | ||||
|             } | ||||
|         private: | ||||
|             std::string m_name; | ||||
|             WildcardPosition m_wildcard; | ||||
|         }; | ||||
|         class TagPattern : public Pattern { | ||||
|         public: | ||||
|             TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} | ||||
|             virtual ~TagPattern(); | ||||
|             virtual bool matches( TestCaseInfo const& testCase ) const { | ||||
|                 return testCase.tags.find( m_tag ) != testCase.tags.end(); | ||||
|             } | ||||
|         private: | ||||
|             std::string m_tag; | ||||
|         }; | ||||
|         class ExcludedPattern : public Pattern { | ||||
|         public: | ||||
|             ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} | ||||
|             virtual ~ExcludedPattern(); | ||||
|             virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } | ||||
|         private: | ||||
|             Ptr<Pattern> m_underlyingPattern; | ||||
|         }; | ||||
|  | ||||
|         struct Filter { | ||||
|             std::vector<Ptr<Pattern> > m_patterns; | ||||
|  | ||||
|             bool matches( TestCaseInfo const& testCase ) const { | ||||
|                 // All patterns in a filter must match for the filter to be a match | ||||
|                 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) | ||||
|                     if( !(*it)->matches( testCase ) ) | ||||
|                         return false; | ||||
|                     return true; | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|     public: | ||||
|         bool hasFilters() const { | ||||
|             return !m_filters.empty(); | ||||
|         } | ||||
|         bool matches( TestCaseInfo const& testCase ) const { | ||||
|             // A TestSpec matches if any filter matches | ||||
|             for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) | ||||
|                 if( it->matches( testCase ) ) | ||||
|                     return true; | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         std::vector<Filter> m_filters; | ||||
|  | ||||
|         friend class TestSpecParser; | ||||
|     }; | ||||
|  | ||||
|  | ||||
|     // -------- deprecated ------- | ||||
|  | ||||
|     class TestCase; | ||||
|  | ||||
|     struct IfFilterMatches{ enum DoWhat { | ||||
|   | ||||
							
								
								
									
										95
									
								
								include/internal/catch_test_spec_parser.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								include/internal/catch_test_spec_parser.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| /* | ||||
|  *  Created by Phil on 15/5/2013. | ||||
|  *  Copyright 2014 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_TEST_SPEC_PARSER_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_test_spec.h" | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     class TestSpecParser { | ||||
|         enum Mode{ None, Name, QuotedName, Tag }; | ||||
|         Mode m_mode; | ||||
|         bool m_exclusion; | ||||
|         std::size_t m_start, m_pos; | ||||
|         std::string m_arg; | ||||
|         TestSpec::Filter m_currentFilter; | ||||
|  | ||||
|     public: | ||||
|         TestSpec testSpec; | ||||
|  | ||||
|     public: | ||||
|         TestSpecParser( std::string const& arg ) : m_mode( None ), m_exclusion( false ), m_start( std::string::npos ), m_arg( arg ) { | ||||
|             for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) | ||||
|                 visitChar( m_arg[m_pos] ); | ||||
|             visitChar( ',' ); | ||||
|         } | ||||
|     private: | ||||
|         void visitChar( char c ) { | ||||
|             if( m_mode == None ) { | ||||
|                 switch( c ) { | ||||
|                 case ' ': return; | ||||
|                 case '~': m_exclusion = true; return; | ||||
|                 case '[': return startNewMode( Tag, ++m_pos ); | ||||
|                 case '"': return startNewMode( QuotedName, ++m_pos ); | ||||
|                 default: startNewMode( Name, m_pos ); break; | ||||
|                 } | ||||
|             } | ||||
|             if( m_mode == Name ) { | ||||
|                 if( c == ',' ) { | ||||
|                     addPattern<TestSpec::NamePattern>(); | ||||
|                     addFilter(); | ||||
|                 } | ||||
|                 else if( c == '[' ) { | ||||
|                     if( subString() == "exclude:" ) | ||||
|                         m_exclusion = true; | ||||
|                     else | ||||
|                         addPattern<TestSpec::NamePattern>(); | ||||
|                     startNewMode( Tag, ++m_pos ); | ||||
|                 } | ||||
|             } | ||||
|             else if( m_mode == QuotedName && c == '"' ) | ||||
|                 addPattern<TestSpec::NamePattern>(); | ||||
|             else if( m_mode == Tag && c == ']' ) | ||||
|                 addPattern<TestSpec::TagPattern>(); | ||||
|         } | ||||
|         void startNewMode( Mode mode, std::size_t start ) { | ||||
|             m_mode = mode; | ||||
|             m_start = start; | ||||
|         } | ||||
|         std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } | ||||
|         template<typename T> | ||||
|         void addPattern() { | ||||
|             std::string token = subString(); | ||||
|             if( startsWith( token, "exclude:" ) ) { | ||||
|                 m_exclusion = true; | ||||
|                 token = token.substr( 8 ); | ||||
|             } | ||||
|             if( !token.empty() ) { | ||||
|                 Ptr<TestSpec::Pattern> pattern = new T( token ); | ||||
|                 if( m_exclusion ) | ||||
|                     pattern = new TestSpec::ExcludedPattern( pattern ); | ||||
|                 m_currentFilter.m_patterns.push_back( pattern ); | ||||
|             } | ||||
|             m_exclusion = false; | ||||
|             m_mode = None; | ||||
|         } | ||||
|         void addFilter() { | ||||
|             if( !m_currentFilter.m_patterns.empty() ) { | ||||
|                 testSpec.m_filters.push_back( m_currentFilter ); | ||||
|                 m_currentFilter = TestSpec::Filter(); | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|     inline TestSpec parseTestSpec( std::string const& arg ) { | ||||
|         return TestSpecParser( arg ).testSpec; | ||||
|     } | ||||
|  | ||||
| } // namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash