diff --git a/include/internal/catch_test_case_info.h b/include/internal/catch_test_case_info.h index aa9dc867..c91ce93b 100644 --- a/include/internal/catch_test_case_info.h +++ b/include/internal/catch_test_case_info.h @@ -43,7 +43,7 @@ namespace Catch { bool throws; }; - class TestCase : protected TestCaseInfo { + class TestCase : public TestCaseInfo { public: TestCase( ITestCase* testCase, TestCaseInfo const& info ); diff --git a/projects/SelfTest/CmdLineTests.cpp b/projects/SelfTest/CmdLineTests.cpp new file mode 100644 index 00000000..27bf2a2f --- /dev/null +++ b/projects/SelfTest/CmdLineTests.cpp @@ -0,0 +1,394 @@ +/* + * Copyright 2013 Two Blue Cubes Ltd + * + * 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) + */ + +#include "catch.hpp" +#include "catch_test_case_info.h" + +#pragma clang diagnostic ignored "-Wpadded" + +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 const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > 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 >::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::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; + + 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 '[': m_mode = Tag; m_start = ++m_pos; return; + case '"': m_mode = QuotedName; m_start = m_pos+1; return; + default: m_mode = Name; m_start = m_pos; break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + m_mode = Tag; + m_start = m_pos+1; + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr 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; + } + + // !TBD: move these to impl + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + +} // namespace Catch + +inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( NULL, "", name, desc, CATCH_INTERNAL_LINEINFO ); } + +TEST_CASE( "Parse test names and tags", "" ) { + + using Catch::parseTestSpec; + using Catch::TestSpec; + + Catch::TestCase tcA = fakeTestCase( "a", "" ); + Catch::TestCase tcB = fakeTestCase( "b", "[one][x]" ); + Catch::TestCase tcC = fakeTestCase( "longer name with spaces", "[two][three][.][x]" ); + Catch::TestCase tcD = fakeTestCase( "zlonger name with spacesz", "" ); + + SECTION( "Empty test spec should have no filters" ) { + TestSpec spec; + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + } + + SECTION( "Test spec from empty string should have no filters" ) { + TestSpec spec = parseTestSpec( "" ); + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches(tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + } + + SECTION( "Test spec from just a comma should have no filters" ) { + TestSpec spec = parseTestSpec( "," ); + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + } + + SECTION( "Test spec from name should have one filter" ) { + TestSpec spec = parseTestSpec( "b" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + } + + SECTION( "Test spec from quoted name should have one filter" ) { + TestSpec spec = parseTestSpec( "\"b\"" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + } + + SECTION( "Test spec from name should have one filter" ) { + TestSpec spec = parseTestSpec( "b" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == false ); + } + + SECTION( "Wildcard at the start" ) { + TestSpec spec = parseTestSpec( "*spaces" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + CHECK( parseTestSpec( "*a" ).matches( tcA ) == true ); + } + SECTION( "Wildcard at the end" ) { + TestSpec spec = parseTestSpec( "long*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + CHECK( parseTestSpec( "a*" ).matches( tcA ) == true ); + } + SECTION( "Wildcard at both ends" ) { + TestSpec spec = parseTestSpec( "*name*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == true ); + CHECK( parseTestSpec( "*a*" ).matches( tcA ) == true ); + } + SECTION( "Just wildcard" ) { + TestSpec spec = parseTestSpec( "*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == true ); + } + + SECTION( "Single tag" ) { + TestSpec spec = parseTestSpec( "[one]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == false ); + } + SECTION( "Single tag, two matches" ) { + TestSpec spec = parseTestSpec( "[x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == true ); + } + SECTION( "Two tags" ) { + TestSpec spec = parseTestSpec( "[two][x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + } + SECTION( "Wildcarded name and tag" ) { + TestSpec spec = parseTestSpec( "*name*[x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "Single tag exclusion" ) { + TestSpec spec = parseTestSpec( "~[one]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + } + SECTION( "One tag exclusion and one tag inclusion" ) { + TestSpec spec = parseTestSpec( "~[two][x]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == false ); + } + SECTION( "One tag exclusion and one wldcarded name inclusion" ) { + TestSpec spec = parseTestSpec( "~[two]*name*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == true ); + } + SECTION( "One tag exclusion, using exclude:, and one wldcarded name inclusion" ) { + TestSpec spec = parseTestSpec( "exclude:[two]*name*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == true ); + } + SECTION( "name exclusion" ) { + TestSpec spec = parseTestSpec( "~b" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == true ); + } + SECTION( "wildcarded name exclusion" ) { + TestSpec spec = parseTestSpec( "~*name*" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "wildcarded name exclusion with tag inclusion" ) { + TestSpec spec = parseTestSpec( "~*name*,[three]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "wildcarded name exclusion, using exclude:, with tag inclusion" ) { + TestSpec spec = parseTestSpec( "exclude:*name*,[three]" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == true ); + CHECK( spec.matches( tcB ) == true ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "two wildcarded names" ) { + TestSpec spec = parseTestSpec( "\"longer*\"\"*spaces\"" ); + CHECK( spec.hasFilters() == true ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == true ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "empty tag" ) { + TestSpec spec = parseTestSpec( "[]" ); + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == false ); + } + SECTION( "empty quoted name" ) { + TestSpec spec = parseTestSpec( "\"\"" ); + CHECK( spec.hasFilters() == false ); + CHECK( spec.matches( tcA ) == false ); + CHECK( spec.matches( tcB ) == false ); + CHECK( spec.matches( tcC ) == false ); + CHECK( spec.matches( tcD ) == false ); + } + +} diff --git a/projects/SelfTest/MessageTests.cpp b/projects/SelfTest/MessageTests.cpp index 0e4a3313..d67a716f 100644 --- a/projects/SelfTest/MessageTests.cpp +++ b/projects/SelfTest/MessageTests.cpp @@ -8,7 +8,7 @@ #include "catch.hpp" -TEST_CASE( "INFO and WARN do not abort tests", "[messages]" ) +TEST_CASE( "INFO and WARN do not abort tests", "[messages][.]" ) { INFO( "this is a " << "message" ); // This should output the message if a failure occurs WARN( "this is a " << "warning" ); // This should always output the message but then continue @@ -74,7 +74,7 @@ TEST_CASE( "Output from all sections is reported", "[failing][messages][.]" ) } } -TEST_CASE( "Standard output from all sections is reported", "[messages]" ) +TEST_CASE( "Standard output from all sections is reported", "[messages][.]" ) { SECTION( "one", "" ) { diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 8a03c958..fffec62a 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -111,7 +111,7 @@ TEST_CASE( "looped tests", "[.][failing]" ) } } -TEST_CASE( "Sends stuff to stdout and stderr", "" ) +TEST_CASE( "Sends stuff to stdout and stderr", "[.]" ) { std::cout << "A string sent directly to stdout" << std::endl; diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index b1468cbc..461f965d 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -251,7 +251,8 @@ TEST_CASE( "selftest/tags", "[tags]" ) { std::string p3 = "[one][two]"; std::string p4 = "[one][two],[three]"; std::string p5 = "[one][two]~[.],[three]"; - + std::string p6 = "[one][two]exclude:[.],[three]"; + SECTION( "single [one] tag", "" ) { Catch::TestCase oneTag = makeTestCase( NULL, "", "test", "[one]", CATCH_INTERNAL_LINEINFO ); @@ -264,6 +265,7 @@ TEST_CASE( "selftest/tags", "[tags]" ) { CHECK( oneTag.matchesTags( p3 ) == false ); CHECK( oneTag.matchesTags( p4 ) == false ); CHECK( oneTag.matchesTags( p5 ) == false ); + CHECK( oneTag.matchesTags( p6 ) == false ); } SECTION( "single [two] tag", "" ) { @@ -278,6 +280,7 @@ TEST_CASE( "selftest/tags", "[tags]" ) { CHECK( oneTag.matchesTags( p3 ) == false ); CHECK( oneTag.matchesTags( p4 ) == false ); CHECK( oneTag.matchesTags( p5 ) == false ); + CHECK( oneTag.matchesTags( p6 ) == false ); } SECTION( "two tags", "" ) { @@ -295,6 +298,7 @@ TEST_CASE( "selftest/tags", "[tags]" ) { CHECK( twoTags.matchesTags( p3 ) == true ); CHECK( twoTags.matchesTags( p4 ) == true ); CHECK( twoTags.matchesTags( p5 ) == true ); + CHECK( twoTags.matchesTags( p6 ) == true ); } SECTION( "complex", "" ) { CHECK( fakeTestCase( "test", "[one][.]" ).matchesTags( p1 ) ); @@ -302,8 +306,10 @@ TEST_CASE( "selftest/tags", "[tags]" ) { CHECK( fakeTestCase( "test", "[three]" ).matchesTags( p4 ) ); CHECK( fakeTestCase( "test", "[three]" ).matchesTags( p5 ) ); CHECK( fakeTestCase( "test", "[three]" ).matchesTags( "[three]~[one]" ) ); + CHECK( fakeTestCase( "test", "[three]" ).matchesTags( "[three]exclude:[one]" ) ); CHECK( fakeTestCase( "test", "[unit][not_apple]" ).matchesTags( "[unit]" ) ); CHECK_FALSE( fakeTestCase( "test", "[unit][not_apple]" ).matchesTags( "[unit]~[not_apple]" ) ); + CHECK_FALSE( fakeTestCase( "test", "[unit][not_apple]" ).matchesTags( "[unit]exclude:[not_apple]" ) ); } SECTION( "one tag with characters either side", "" ) { @@ -499,7 +505,7 @@ private: }; // !TBD: This will be folded into Text class -TEST_CASE( "Strings can be rendered with colour", "[colour]" ) { +TEST_CASE( "Strings can be rendered with colour", "[colour][.]" ) { { ColourString cs( "hello" ); diff --git a/projects/VS2008/TestCatch/TestCatch/TestCatch.vcproj b/projects/VS2008/TestCatch/TestCatch/TestCatch.vcproj index d40c925d..d4cb0c97 100644 --- a/projects/VS2008/TestCatch/TestCatch/TestCatch.vcproj +++ b/projects/VS2008/TestCatch/TestCatch/TestCatch.vcproj @@ -351,10 +351,6 @@ RelativePath="..\..\..\SelfTest\ClassTests.cpp" > - - diff --git a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index cbcaf52a..01935b03 100644 --- a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj +++ b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 26847E5F16BBADB40043B9C1 /* catch_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26847E5D16BBADB40043B9C1 /* catch_message.cpp */; }; 26948286179A9AB900ED166E /* SectionTrackerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26948284179A9AB900ED166E /* SectionTrackerTests.cpp */; }; 2694A1FD16A0000E004816E3 /* catch_text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2694A1FB16A0000E004816E3 /* catch_text.cpp */; }; + 26E1B7D319213BC900812682 /* CmdLineTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E1B7D119213BC900812682 /* CmdLineTests.cpp */; }; 4A45DA2416161EF9004F8D6B /* catch_console_colour.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2316161EF9004F8D6B /* catch_console_colour.cpp */; }; 4A45DA2716161F1F004F8D6B /* catch_ptr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2616161F1F004F8D6B /* catch_ptr.cpp */; }; 4A45DA2916161F3D004F8D6B /* catch_streambuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2816161F3D004F8D6B /* catch_streambuf.cpp */; }; @@ -85,6 +86,7 @@ 269831E719121CA500BB0CE0 /* catch_reporter_compact.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_compact.hpp; sourceTree = ""; }; 26AEAF1617BEA18E009E32C9 /* catch_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_platform.h; sourceTree = ""; }; 26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = ""; }; + 26E1B7D119213BC900812682 /* CmdLineTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CmdLineTests.cpp; path = ../../../SelfTest/CmdLineTests.cpp; sourceTree = ""; }; 4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_info.hpp; sourceTree = ""; }; 4A084F1D15DAD15F0027E631 /* catch_test_spec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_test_spec.h; sourceTree = ""; }; 4A3D7DD01503869D005F9203 /* catch_matchers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_matchers.hpp; sourceTree = ""; }; @@ -193,6 +195,7 @@ isa = PBXGroup; children = ( 26948284179A9AB900ED166E /* SectionTrackerTests.cpp */, + 26E1B7D119213BC900812682 /* CmdLineTests.cpp */, ); name = "Introspective Tests"; sourceTree = ""; @@ -520,6 +523,7 @@ 4AEE0328161434FD0071E950 /* catch_xmlwriter.cpp in Sources */, 4A45DA2416161EF9004F8D6B /* catch_console_colour.cpp in Sources */, 4A45DA2716161F1F004F8D6B /* catch_ptr.cpp in Sources */, + 26E1B7D319213BC900812682 /* CmdLineTests.cpp in Sources */, 4A45DA2916161F3D004F8D6B /* catch_streambuf.cpp in Sources */, 4A45DA2B16161F79004F8D6B /* catch_interfaces_registry_hub.cpp in Sources */, 4A45DA2D16161FA2004F8D6B /* catch_interfaces_capture.cpp in Sources */,