Alien-catch
view release on metacpan or search on metacpan
src/catch.hpp view on Meta::CPAN
public:
NamePattern( std::string const& name );
virtual ~NamePattern();
virtual bool matches( TestCaseInfo const& testCase ) const override;
private:
WildcardPattern m_wildcardPattern;
};
class TagPattern : public Pattern {
public:
TagPattern( std::string const& tag );
virtual ~TagPattern();
virtual bool matches( TestCaseInfo const& testCase ) const override;
private:
std::string m_tag;
};
class ExcludedPattern : public Pattern {
public:
ExcludedPattern( PatternPtr const& underlyingPattern );
virtual ~ExcludedPattern();
virtual bool matches( TestCaseInfo const& testCase ) const override;
private:
PatternPtr m_underlyingPattern;
};
struct Filter {
std::vector<PatternPtr> m_patterns;
bool matches( TestCaseInfo const& testCase ) const;
};
public:
bool hasFilters() const;
bool matches( TestCaseInfo const& testCase ) const;
private:
std::vector<Filter> m_filters;
friend class TestSpecParser;
};
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif
// end catch_test_spec.h
// start catch_interfaces_tag_alias_registry.h
#include <string>
namespace Catch {
struct TagAlias;
struct ITagAliasRegistry {
virtual ~ITagAliasRegistry();
// Nullptr if not present
virtual TagAlias const* find( std::string const& alias ) const = 0;
virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
static ITagAliasRegistry const& get();
};
} // end namespace Catch
// end catch_interfaces_tag_alias_registry.h
namespace Catch {
class TestSpecParser {
enum Mode{ None, Name, QuotedName, Tag, EscapedName };
Mode m_mode = None;
bool m_exclusion = false;
std::size_t m_start = std::string::npos, m_pos = 0;
std::string m_arg;
std::vector<std::size_t> m_escapeChars;
TestSpec::Filter m_currentFilter;
TestSpec m_testSpec;
ITagAliasRegistry const* m_tagAliases = nullptr;
public:
TestSpecParser( ITagAliasRegistry const& tagAliases );
TestSpecParser& parse( std::string const& arg );
TestSpec testSpec();
private:
void visitChar( char c );
void startNewMode( Mode mode, std::size_t start );
void escape();
std::string subString() const;
template<typename T>
void addPattern() {
std::string token = subString();
for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
m_escapeChars.clear();
if( startsWith( token, "exclude:" ) ) {
m_exclusion = true;
token = token.substr( 8 );
}
if( !token.empty() ) {
TestSpec::PatternPtr pattern = std::make_shared<T>( token );
if( m_exclusion )
pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
m_currentFilter.m_patterns.push_back( pattern );
}
m_exclusion = false;
m_mode = None;
}
void addFilter();
};
TestSpec parseTestSpec( std::string const& arg );
} // namespace Catch
#ifdef __clang__
#pragma clang diagnostic pop
src/catch.hpp view on Meta::CPAN
using TestCaseNode = Node<TestCaseStats, SectionNode>;
using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
using TestRunNode = Node<TestRunStats, TestGroupNode>;
CumulativeReporterBase( ReporterConfig const& _config )
: m_config( _config.fullConfig() ),
stream( _config.stream() )
{
m_reporterPrefs.shouldRedirectStdOut = false;
if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
CATCH_ERROR( "Verbosity level not supported by this reporter" );
}
~CumulativeReporterBase() override = default;
ReporterPreferences getPreferences() const override {
return m_reporterPrefs;
}
static std::set<Verbosity> getSupportedVerbosities() {
return { Verbosity::Normal };
}
void testRunStarting( TestRunInfo const& ) override {}
void testGroupStarting( GroupInfo const& ) override {}
void testCaseStarting( TestCaseInfo const& ) override {}
void sectionStarting( SectionInfo const& sectionInfo ) override {
SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
std::shared_ptr<SectionNode> node;
if( m_sectionStack.empty() ) {
if( !m_rootSection )
m_rootSection = std::make_shared<SectionNode>( incompleteStats );
node = m_rootSection;
}
else {
SectionNode& parentNode = *m_sectionStack.back();
auto it =
std::find_if( parentNode.childSections.begin(),
parentNode.childSections.end(),
BySectionInfo( sectionInfo ) );
if( it == parentNode.childSections.end() ) {
node = std::make_shared<SectionNode>( incompleteStats );
parentNode.childSections.push_back( node );
}
else
node = *it;
}
m_sectionStack.push_back( node );
m_deepestSection = std::move(node);
}
void assertionStarting(AssertionInfo const&) override {}
bool assertionEnded(AssertionStats const& assertionStats) override {
assert(!m_sectionStack.empty());
// AssertionResult holds a pointer to a temporary DecomposedExpression,
// which getExpandedExpression() calls to build the expression string.
// Our section stack copy of the assertionResult will likely outlive the
// temporary, so it must be expanded or discarded now to avoid calling
// a destroyed object later.
prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) );
SectionNode& sectionNode = *m_sectionStack.back();
sectionNode.assertions.push_back(assertionStats);
return true;
}
void sectionEnded(SectionStats const& sectionStats) override {
assert(!m_sectionStack.empty());
SectionNode& node = *m_sectionStack.back();
node.stats = sectionStats;
m_sectionStack.pop_back();
}
void testCaseEnded(TestCaseStats const& testCaseStats) override {
auto node = std::make_shared<TestCaseNode>(testCaseStats);
assert(m_sectionStack.size() == 0);
node->children.push_back(m_rootSection);
m_testCases.push_back(node);
m_rootSection.reset();
assert(m_deepestSection);
m_deepestSection->stdOut = testCaseStats.stdOut;
m_deepestSection->stdErr = testCaseStats.stdErr;
}
void testGroupEnded(TestGroupStats const& testGroupStats) override {
auto node = std::make_shared<TestGroupNode>(testGroupStats);
node->children.swap(m_testCases);
m_testGroups.push_back(node);
}
void testRunEnded(TestRunStats const& testRunStats) override {
auto node = std::make_shared<TestRunNode>(testRunStats);
node->children.swap(m_testGroups);
m_testRuns.push_back(node);
testRunEndedCumulative();
}
virtual void testRunEndedCumulative() = 0;
void skipTest(TestCaseInfo const&) override {}
IConfigPtr m_config;
std::ostream& stream;
std::vector<AssertionStats> m_assertions;
std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;
std::vector<std::shared_ptr<TestCaseNode>> m_testCases;
std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;
std::vector<std::shared_ptr<TestRunNode>> m_testRuns;
std::shared_ptr<SectionNode> m_rootSection;
std::shared_ptr<SectionNode> m_deepestSection;
std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
ReporterPreferences m_reporterPrefs;
};
template<char C>
char const* getLineOfChars() {
static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
if( !*line ) {
std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
}
src/catch.hpp view on Meta::CPAN
std::string extractClassName( StringRef const& classOrQualifiedMethodName );
///////////////////////////////////////////////////////////////////////////
} // end namespace Catch
// end catch_test_case_registry_impl.h
// start catch_reporter_registry.h
#include <map>
namespace Catch {
class ReporterRegistry : public IReporterRegistry {
public:
~ReporterRegistry() override;
IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override;
void registerReporter( std::string const& name, IReporterFactoryPtr const& factory );
void registerListener( IReporterFactoryPtr const& factory );
FactoryMap const& getFactories() const override;
Listeners const& getListeners() const override;
private:
FactoryMap m_factories;
Listeners m_listeners;
};
}
// end catch_reporter_registry.h
// start catch_tag_alias_registry.h
// start catch_tag_alias.h
#include <string>
namespace Catch {
struct TagAlias {
TagAlias(std::string const& _tag, SourceLineInfo _lineInfo);
std::string tag;
SourceLineInfo lineInfo;
};
} // end namespace Catch
// end catch_tag_alias.h
#include <map>
namespace Catch {
class TagAliasRegistry : public ITagAliasRegistry {
public:
~TagAliasRegistry() override;
TagAlias const* find( std::string const& alias ) const override;
std::string expandAliases( std::string const& unexpandedTestSpec ) const override;
void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
private:
std::map<std::string, TagAlias> m_registry;
};
} // end namespace Catch
// end catch_tag_alias_registry.h
// start catch_startup_exception_registry.h
#include <vector>
#include <exception>
namespace Catch {
class StartupExceptionRegistry {
public:
void add(std::exception_ptr const& exception) noexcept;
std::vector<std::exception_ptr> const& getExceptions() const noexcept;
private:
std::vector<std::exception_ptr> m_exceptions;
};
} // end namespace Catch
// end catch_startup_exception_registry.h
// start catch_singletons.hpp
namespace Catch {
struct ISingleton {
virtual ~ISingleton();
};
void addSingleton( ISingleton* singleton );
void cleanupSingletons();
template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
class Singleton : SingletonImplT, public ISingleton {
static auto getInternal() -> Singleton* {
static Singleton* s_instance = nullptr;
if( !s_instance ) {
s_instance = new Singleton;
addSingleton( s_instance );
}
return s_instance;
}
public:
static auto get() -> InterfaceT const& {
return *getInternal();
}
static auto getMutable() -> MutableInterfaceT& {
return *getInternal();
}
};
} // namespace Catch
src/catch.hpp view on Meta::CPAN
}
auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string {
return std::string( lhs ) + std::string( rhs );
}
auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string {
return std::string( lhs ) + std::string( rhs );
}
auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
return os.write(str.currentData(), str.size());
}
auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {
lhs.append(rhs.currentData(), rhs.size());
return lhs;
}
} // namespace Catch
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
// end catch_stringref.cpp
// start catch_tag_alias.cpp
namespace Catch {
TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}
}
// end catch_tag_alias.cpp
// start catch_tag_alias_autoregistrar.cpp
namespace Catch {
RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
CATCH_TRY {
getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
} CATCH_CATCH_ALL {
// Do not throw when constructing global objects, instead register the exception to be processed later
getMutableRegistryHub().registerStartupException();
}
}
}
// end catch_tag_alias_autoregistrar.cpp
// start catch_tag_alias_registry.cpp
#include <sstream>
namespace Catch {
TagAliasRegistry::~TagAliasRegistry() {}
TagAlias const* TagAliasRegistry::find( std::string const& alias ) const {
auto it = m_registry.find( alias );
if( it != m_registry.end() )
return &(it->second);
else
return nullptr;
}
std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
std::string expandedTestSpec = unexpandedTestSpec;
for( auto const& registryKvp : m_registry ) {
std::size_t pos = expandedTestSpec.find( registryKvp.first );
if( pos != std::string::npos ) {
expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
registryKvp.second.tag +
expandedTestSpec.substr( pos + registryKvp.first.size() );
}
}
return expandedTestSpec;
}
void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {
CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'),
"error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo );
CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
"error: tag alias, '" << alias << "' already registered.\n"
<< "\tFirst seen at: " << find(alias)->lineInfo << "\n"
<< "\tRedefined at: " << lineInfo );
}
ITagAliasRegistry::~ITagAliasRegistry() {}
ITagAliasRegistry const& ITagAliasRegistry::get() {
return getRegistryHub().getTagAliasRegistry();
}
} // end namespace Catch
// end catch_tag_alias_registry.cpp
// start catch_test_case_info.cpp
#include <cctype>
#include <exception>
#include <algorithm>
#include <sstream>
namespace Catch {
namespace {
TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
if( startsWith( tag, '.' ) ||
tag == "!hide" )
return TestCaseInfo::IsHidden;
else if( tag == "!throws" )
return TestCaseInfo::Throws;
else if( tag == "!shouldfail" )
return TestCaseInfo::ShouldFail;
else if( tag == "!mayfail" )
return TestCaseInfo::MayFail;
else if( tag == "!nonportable" )
return TestCaseInfo::NonPortable;
else if( tag == "!benchmark" )
return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );
else
return TestCaseInfo::None;
}
bool isReservedTag( std::string const& tag ) {
return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );
}
void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
CATCH_ENFORCE( !isReservedTag(tag),
"Tag name: [" << tag << "] is not allowed.\n"
<< "Tag names starting with non alpha-numeric characters are reserved\n"
<< _lineInfo );
}
}
TestCase makeTestCase( ITestInvoker* _testCase,
std::string const& _className,
src/catch.hpp view on Meta::CPAN
#include <algorithm>
#include <string>
#include <vector>
#include <memory>
namespace Catch {
TestSpec::Pattern::~Pattern() = default;
TestSpec::NamePattern::~NamePattern() = default;
TestSpec::TagPattern::~TagPattern() = default;
TestSpec::ExcludedPattern::~ExcludedPattern() = default;
TestSpec::NamePattern::NamePattern( std::string const& name )
: m_wildcardPattern( toLower( name ), CaseSensitive::No )
{}
bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
return m_wildcardPattern.matches( toLower( testCase.name ) );
}
TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
return std::find(begin(testCase.lcaseTags),
end(testCase.lcaseTags),
m_tag) != end(testCase.lcaseTags);
}
TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
// All patterns in a filter must match for the filter to be a match
for( auto const& pattern : m_patterns ) {
if( !pattern->matches( testCase ) )
return false;
}
return true;
}
bool TestSpec::hasFilters() const {
return !m_filters.empty();
}
bool TestSpec::matches( TestCaseInfo const& testCase ) const {
// A TestSpec matches if any filter matches
for( auto const& filter : m_filters )
if( filter.matches( testCase ) )
return true;
return false;
}
}
// end catch_test_spec.cpp
// start catch_test_spec_parser.cpp
namespace Catch {
TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
m_mode = None;
m_exclusion = false;
m_start = std::string::npos;
m_arg = m_tagAliases->expandAliases( arg );
m_escapeChars.clear();
for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
visitChar( m_arg[m_pos] );
if( m_mode == Name )
addPattern<TestSpec::NamePattern>();
return *this;
}
TestSpec TestSpecParser::testSpec() {
addFilter();
return m_testSpec;
}
void TestSpecParser::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 );
case '\\': return escape();
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( c == '\\' )
escape();
}
else if( m_mode == EscapedName )
m_mode = Name;
else if( m_mode == QuotedName && c == '"' )
addPattern<TestSpec::NamePattern>();
else if( m_mode == Tag && c == ']' )
addPattern<TestSpec::TagPattern>();
}
void TestSpecParser::startNewMode( Mode mode, std::size_t start ) {
m_mode = mode;
m_start = start;
}
void TestSpecParser::escape() {
if( m_mode == None )
m_start = m_pos;
m_mode = EscapedName;
m_escapeChars.push_back( m_pos );
}
std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
void TestSpecParser::addFilter() {
if( !m_currentFilter.m_patterns.empty() ) {
m_testSpec.m_filters.push_back( m_currentFilter );
( run in 1.607 second using v1.01-cache-2.11-cpan-5b529ec07f3 )