mirror of
https://github.com/catchorg/Catch2.git
synced 2024-12-23 03:43:28 +01:00
4f47d1c6c1
This also required some refactoring of how the pattern matching works. This means that the concepts of include and exclude patterns are no longer unified, with exclusion patterns working as just negation of an inclusion patterns (which led to including hidden tags by default, as they did not match the exclusion), but rather both include and exclude patterns are handled separately. The new logic is that given a filter and a test case, the test case must match _all_ include patterns and _no_ exclude patterns to be included by the filter. Furthermore, if the test case is hidden, then the filter must have at least one include pattern for the test case to be used. Closes #1184
105 lines
3.1 KiB
C++
105 lines
3.1 KiB
C++
/*
|
|
* Created by Martin on 19/07/2017.
|
|
*
|
|
* 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_test_spec.h"
|
|
#include "catch_string_manip.h"
|
|
#include "catch_interfaces_config.h"
|
|
|
|
#include <algorithm>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <memory>
|
|
|
|
namespace Catch {
|
|
|
|
TestSpec::Pattern::Pattern( std::string const& name )
|
|
: m_name( name )
|
|
{}
|
|
|
|
TestSpec::Pattern::~Pattern() = default;
|
|
|
|
std::string const& TestSpec::Pattern::name() const {
|
|
return m_name;
|
|
}
|
|
|
|
|
|
TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString )
|
|
: Pattern( filterString )
|
|
, m_wildcardPattern( toLower( name ), CaseSensitive::No )
|
|
{}
|
|
|
|
bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
|
|
return m_wildcardPattern.matches( testCase.name );
|
|
}
|
|
|
|
|
|
TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString )
|
|
: Pattern( filterString )
|
|
, 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);
|
|
}
|
|
|
|
bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
|
|
bool should_use = !testCase.isHidden();
|
|
for (auto const& pattern : m_required) {
|
|
should_use = true;
|
|
if (!pattern->matches(testCase)) {
|
|
return false;
|
|
}
|
|
}
|
|
for (auto const& pattern : m_forbidden) {
|
|
if (pattern->matches(testCase)) {
|
|
return false;
|
|
}
|
|
}
|
|
return should_use;
|
|
}
|
|
|
|
std::string TestSpec::Filter::name() const {
|
|
std::string name;
|
|
for (auto const& p : m_required) {
|
|
name += p->name();
|
|
}
|
|
for (auto const& p : m_forbidden) {
|
|
name += p->name();
|
|
}
|
|
return name;
|
|
}
|
|
|
|
|
|
bool TestSpec::hasFilters() const {
|
|
return !m_filters.empty();
|
|
}
|
|
|
|
bool TestSpec::matches( TestCaseInfo const& testCase ) const {
|
|
return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } );
|
|
}
|
|
|
|
TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const
|
|
{
|
|
Matches matches( m_filters.size() );
|
|
std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){
|
|
std::vector<TestCase const*> currentMatches;
|
|
for( auto const& test : testCases )
|
|
if( isThrowSafe( test, config ) && filter.matches( test ) )
|
|
currentMatches.emplace_back( &test );
|
|
return FilterMatch{ filter.name(), currentMatches };
|
|
} );
|
|
return matches;
|
|
}
|
|
|
|
const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{
|
|
return (m_invalidArgs);
|
|
}
|
|
|
|
}
|