diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2ead6759..385a594c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,7 +14,7 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif()
-project(Catch2 LANGUAGES CXX VERSION 2.10.0)
+project(Catch2 LANGUAGES CXX VERSION 2.10.1)
# Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
diff --git a/README.md b/README.md
index 2b806cd4..f5d7017b 100644
--- a/README.md
+++ b/README.md
@@ -5,11 +5,11 @@
[](https://travis-ci.org/catchorg/Catch2)
[](https://ci.appveyor.com/project/catchorg/catch2)
[](https://codecov.io/gh/catchorg/Catch2)
-[](https://wandbox.org/permlink/00GdTUbFWaV3bNah)
+[](https://wandbox.org/permlink/oT2uthEb4CcTd0hb)
[](https://discord.gg/4CWS9zD)
-The latest version of the single header can be downloaded directly using this link
+The latest version of the single header can be downloaded directly using this link
## Catch2 is released!
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 0af35c67..8f8823af 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -2,6 +2,7 @@
# Release notes
**Contents**
+[2.10.1](#2101)
[2.10.0](#2100)
[2.9.2](#292)
[2.9.1](#291)
@@ -29,6 +30,23 @@
[Even Older versions](#even-older-versions)
+## 2.10.1
+
+### Improvements
+* Catch2 now guards itself against `min` and `max` macros from `windows.h` (#1772)
+* Templated tests will now compile with ICC (#1748)
+* `WithinULP` matcher now uses scientific notation for stringification (#1760)
+
+
+### Fixes
+* Templated tests no longer trigger `-Wunused-templates` (#1762)
+* Suppressed clang-analyzer false positive in context getter (#1230, #1735)
+
+
+### Miscellaneous
+* CMake no longer prohibits in-tree build when Catch2 is used as a subproject (#1773, #1774)
+
+
## 2.10.0
diff --git a/include/catch.hpp b/include/catch.hpp
index 5d38092e..0831a1b2 100644
--- a/include/catch.hpp
+++ b/include/catch.hpp
@@ -11,7 +11,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 10
-#define CATCH_VERSION_PATCH 0
+#define CATCH_VERSION_PATCH 1
#ifdef __clang__
# pragma clang system_header
diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp
index bb5b0616..b64212ca 100644
--- a/include/internal/catch_version.cpp
+++ b/include/internal/catch_version.cpp
@@ -37,7 +37,7 @@ namespace Catch {
}
Version const& libraryVersion() {
- static Version version( 2, 10, 0, "", 0 );
+ static Version version( 2, 10, 1, "", 0 );
return version;
}
diff --git a/single_include/catch2/catch.hpp b/single_include/catch2/catch.hpp
index 391db530..5d104bc4 100644
--- a/single_include/catch2/catch.hpp
+++ b/single_include/catch2/catch.hpp
@@ -1,6 +1,6 @@
/*
- * Catch v2.10.0
- * Generated: 2019-10-13 22:24:46.755734
+ * Catch v2.10.1
+ * Generated: 2019-10-20 20:52:21.372334
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved.
@@ -15,7 +15,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 10
-#define CATCH_VERSION_PATCH 0
+#define CATCH_VERSION_PATCH 1
#ifdef __clang__
# pragma clang system_header
@@ -163,6 +163,11 @@ namespace Catch {
# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
_Pragma( "clang diagnostic pop" )
+# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
+ _Pragma( "clang diagnostic push" ) \
+ _Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
+# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
+ _Pragma( "clang diagnostic pop" )
#endif // __clang__
////////////////////////////////////////////////////////////////////////////////
@@ -409,6 +414,19 @@ namespace Catch {
# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS
#endif
+#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
+# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
+# undef CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS
+#elif defined(__clang__) && (__clang_major__ < 5)
+# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
+# undef CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS
+#endif
+
+#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS)
+# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
+# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS
+#endif
+
#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
#define CATCH_TRY if ((true))
#define CATCH_CATCH_ALL if ((false))
@@ -775,35 +793,49 @@ inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noex
template struct TypeList {};\
template\
constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\
+ template class...> struct TemplateTypeList{};\
+ template class...Cs>\
+ constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\
+ template\
+ struct append;\
+ template\
+ struct rewrap;\
+ template class, typename...>\
+ struct create;\
+ template class, typename>\
+ struct convert;\
\
- template class L1, typename...E1, template class L2, typename...E2> \
- constexpr auto append(L1, L2) noexcept -> L1 { return {}; }\
+ template \
+ struct append { using type = T; };\
template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\
- constexpr auto append(L1, L2, Rest...) noexcept -> decltype(append(L1{}, Rest{}...)) { return {}; }\
+ struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\
template< template class L1, typename...E1, typename...Rest>\
- constexpr auto append(L1, TypeList, Rest...) noexcept -> L1 { return {}; }\
+ struct append, TypeList, Rest...> { using type = L1; };\
\
template< template class Container, template class List, typename...elems>\
- constexpr auto rewrap(List) noexcept -> TypeList> { return {}; }\
+ struct rewrap, List> { using type = TypeList>; };\
template< template class Container, template class List, class...Elems, typename...Elements>\
- constexpr auto rewrap(List,Elements...) noexcept -> decltype(append(TypeList>{}, rewrap(Elements{}...))) { return {}; }\
+ struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\
\
template class Final, template< typename...> class...Containers, typename...Types>\
- constexpr auto create(TypeList) noexcept -> decltype(append(Final<>{}, rewrap(Types{}...)...)) { return {}; }\
+ struct create, TypeList> { using type = typename append, typename rewrap, Types...>::type...>::type; };\
template class Final, template class List, typename...Ts>\
- constexpr auto convert(const List& ) noexcept -> decltype(append(Final<>{},TypeList{}...)) { return {}; }
+ struct convert> { using type = typename append,TypeList...>::type; };
#define INTERNAL_CATCH_NTTP_1(signature, ...)\
template struct Nttp{};\
template\
constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
+ template class...> struct NttpTemplateTypeList{};\
+ template class...Cs>\
+ constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList { return {}; } \
\
template< template class Container, template class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
- constexpr auto rewrap(List<__VA_ARGS__>) noexcept -> TypeList> { return {}; }\
+ struct rewrap, List<__VA_ARGS__>> { using type = TypeList>; };\
template< template class Container, template class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
- constexpr auto rewrap(List<__VA_ARGS__>,Elements...elems) noexcept -> decltype(append(TypeList>{}, rewrap(elems...))) { return {}; }\
+ struct rewrap, List<__VA_ARGS__>, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\
template class Final, template class...Containers, typename...Types>\
- constexpr auto create(TypeList) noexcept -> decltype(append(Final<>{}, rewrap(Types{}...)...)) { return {}; }
+ struct create, TypeList> { using type = typename append, typename rewrap, Types...>::type...>::type; };
#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
@@ -1050,6 +1082,7 @@ struct AutoReg : NonCopyable {
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
+ CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
namespace {\
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
@@ -1073,6 +1106,7 @@ struct AutoReg : NonCopyable {
}\
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
+ CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
@@ -1094,6 +1128,7 @@ struct AutoReg : NonCopyable {
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
+ CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
template static void TestFuncName(); \
namespace {\
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
@@ -1111,7 +1146,7 @@ struct AutoReg : NonCopyable {
} \
}; \
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
- using TestInit = decltype(create(TypeList{})); \
+ using TestInit = typename create()), TypeList>::type; \
TestInit t; \
t.reg_tests(); \
return 0; \
@@ -1120,6 +1155,7 @@ struct AutoReg : NonCopyable {
} \
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
+ CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
template \
static void TestFuncName()
@@ -1141,6 +1177,7 @@ struct AutoReg : NonCopyable {
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
template static void TestFunc(); \
namespace {\
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
@@ -1154,13 +1191,14 @@ struct AutoReg : NonCopyable {
} \
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
- using TestInit = decltype(convert(std::declval())); \
+ using TestInit = typename convert::type; \
TestInit t; \
t.reg_tests(); \
return 0; \
}(); \
}}\
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+ CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
template \
static void TestFunc()
@@ -1170,6 +1208,7 @@ struct AutoReg : NonCopyable {
#define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
+ CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
namespace {\
namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
INTERNAL_CATCH_TYPE_GEN\
@@ -1193,6 +1232,7 @@ struct AutoReg : NonCopyable {
}\
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS\
+ CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS\
INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
@@ -1214,6 +1254,7 @@ struct AutoReg : NonCopyable {
#define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
+ CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
template \
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName ) { \
void test();\
@@ -1234,7 +1275,7 @@ struct AutoReg : NonCopyable {
}\
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
- using TestInit = decltype(create(TypeList{}));\
+ using TestInit = typename create()), TypeList>::type;\
TestInit t;\
t.reg_tests();\
return 0;\
@@ -1243,6 +1284,7 @@ struct AutoReg : NonCopyable {
}\
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \
+ CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
template \
void TestName::test()
@@ -1264,6 +1306,7 @@ struct AutoReg : NonCopyable {
#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
+ CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
template \
struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName ) { \
void test();\
@@ -1280,13 +1323,14 @@ struct AutoReg : NonCopyable {
}\
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
- using TestInit = decltype(convert(std::declval()));\
+ using TestInit = typename convert::type;\
TestInit t;\
t.reg_tests();\
return 0;\
}(); \
}}\
CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
+ CATCH_INTERNAL_UNSUPPRESS_UNUSED_TEMPLATE_WARNINGS \
template \
void TestName::test()
@@ -4311,6 +4355,7 @@ namespace Catch {
{
if( !IMutableContext::currentContext )
IMutableContext::createContext();
+ // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
return *IMutableContext::currentContext;
}
@@ -4484,10 +4529,10 @@ namespace Catch {
using state_type = std::uint64_t;
public:
using result_type = std::uint32_t;
- static constexpr result_type min() {
+ static constexpr result_type (min)() {
return 0;
}
- static constexpr result_type max() {
+ static constexpr result_type (max)() {
return static_cast(-1);
}
@@ -5082,14 +5127,16 @@ namespace Catch {
std::vector tests;
};
using Matches = std::vector;
+ using vectorStrings = std::vector;
bool hasFilters() const;
bool matches( TestCaseInfo const& testCase ) const;
Matches matchesByFilter( std::vector const& testCases, IConfig const& config ) const;
+ const vectorStrings & getInvalidArgs() const;
private:
std::vector m_filters;
-
+ std::vector m_invalidArgs;
friend class TestSpecParser;
};
}
@@ -5143,7 +5190,7 @@ namespace Catch {
TestSpec testSpec();
private:
- void visitChar( char c );
+ bool visitChar( char c );
void startNewMode( Mode mode );
bool processNoneChar( char c );
void processNameChar( char c );
@@ -5153,6 +5200,8 @@ namespace Catch {
bool isControlChar( char c ) const;
void saveLastMode();
void revertBackToLastMode();
+ void addFilter();
+ bool separate();
template
void addPattern() {
@@ -5176,7 +5225,12 @@ namespace Catch {
m_mode = None;
}
- void addFilter();
+ inline void addCharToPattern(char c) {
+ m_substring += c;
+ m_patternName += c;
+ m_realPatternPos++;
+ }
+
};
TestSpec parseTestSpec( std::string const& arg );
@@ -5584,6 +5638,8 @@ namespace Catch {
virtual void noMatchingTestCases( std::string const& spec ) = 0;
+ virtual void reportInvalidArguments(std::string const&) {}
+
virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
@@ -5676,6 +5732,8 @@ namespace Catch {
void noMatchingTestCases(std::string const&) override {}
+ void reportInvalidArguments(std::string const&) override {}
+
void testRunStarting(TestRunInfo const& _testRunInfo) override {
currentTestRunInfo = _testRunInfo;
}
@@ -6079,6 +6137,8 @@ namespace Catch {
void noMatchingTestCases(std::string const& spec) override;
+ void reportInvalidArguments(std::string const&arg) override;
+
void assertionStarting(AssertionInfo const&) override;
bool assertionEnded(AssertionStats const& _assertionStats) override;
@@ -9544,9 +9604,15 @@ namespace Catch {
if( !line.empty() && !startsWith( line, '#' ) ) {
if( !startsWith( line, '"' ) )
line = '"' + line + '"';
- config.testsOrTags.push_back( line + ',' );
+ config.testsOrTags.push_back( line );
+ config.testsOrTags.push_back( "," );
+
}
}
+ //Remove comma in the end
+ if(!config.testsOrTags.empty())
+ config.testsOrTags.erase( config.testsOrTags.end()-1 );
+
return ParserResult::ok( ParseResultType::Matched );
};
auto const setTestOrder = [&]( std::string const& order ) {
@@ -10755,6 +10821,8 @@ namespace Catch {
void noMatchingTestCases( std::string const& spec ) override;
+ void reportInvalidArguments(std::string const&arg) override;
+
static std::set getSupportedVerbosities();
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
@@ -11278,14 +11346,17 @@ FP step(FP start, FP direction, uint64_t steps) {
return start;
}
-namespace {
-
- // Performs equivalent check of std::fabs(lhs - rhs) <= margin
- // But without the subtraction to allow for INFINITY in comparison
- bool marginComparison(double lhs, double rhs, double margin) {
- return (lhs + margin >= rhs) && (rhs + margin >= lhs);
- }
+// Performs equivalent check of std::fabs(lhs - rhs) <= margin
+// But without the subtraction to allow for INFINITY in comparison
+bool marginComparison(double lhs, double rhs, double margin) {
+ return (lhs + margin >= rhs) && (rhs + margin >= lhs);
+}
+template
+void write(std::ostream& out, FloatingPoint num) {
+ out << std::scientific
+ << std::setprecision(std::numeric_limits::max_digits10 - 1)
+ << num;
}
} // end anonymous namespace
@@ -11317,7 +11388,7 @@ namespace Floating {
WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType)
:m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
CATCH_ENFORCE(m_type == FloatingPointKind::Double
- || m_ulps < std::numeric_limits::max(),
+ || m_ulps < (std::numeric_limits::max)(),
"Provided ULP is impossibly large for a float comparison.");
}
@@ -11345,27 +11416,28 @@ namespace Floating {
std::string WithinUlpsMatcher::describe() const {
std::stringstream ret;
- ret << "is within " << m_ulps << " ULPs of " << ::Catch::Detail::stringify(m_target);
+ ret << "is within " << m_ulps << " ULPs of ";
if (m_type == FloatingPointKind::Float) {
+ write(ret, static_cast(m_target));
ret << 'f';
+ } else {
+ write(ret, m_target);
}
ret << " ([";
- ret << std::fixed << std::setprecision(std::numeric_limits::max_digits10);
if (m_type == FloatingPointKind::Double) {
- ret << step(m_target, static_cast(-INFINITY), m_ulps)
- << ", "
- << step(m_target, static_cast(INFINITY), m_ulps);
+ write(ret, step(m_target, static_cast(-INFINITY), m_ulps));
+ ret << ", ";
+ write(ret, step(m_target, static_cast( INFINITY), m_ulps));
} else {
- ret << step(static_cast(m_target), -INFINITY, m_ulps)
- << ", "
- << step(static_cast(m_target), INFINITY, m_ulps);
+ write(ret, step(static_cast(m_target), -INFINITY, m_ulps));
+ ret << ", ";
+ write(ret, step(static_cast(m_target), INFINITY, m_ulps));
}
ret << "])";
return ret.str();
- //return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
}
WithinRelMatcher::WithinRelMatcher(double target, double epsilon):
@@ -11376,7 +11448,7 @@ namespace Floating {
}
bool WithinRelMatcher::match(double const& matchee) const {
- const auto relMargin = m_epsilon * std::max(std::fabs(matchee), std::fabs(m_target));
+ const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target));
return marginComparison(matchee, m_target,
std::isinf(relMargin)? 0 : relMargin);
}
@@ -12983,8 +13055,9 @@ namespace Catch {
{
auto const& allTestCases = getAllTestCasesSorted(*m_config);
m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
+ auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
- if (m_matches.empty()) {
+ if (m_matches.empty() && invalidArgs.empty()) {
for (auto const& test : allTestCases)
if (!test.isHidden())
m_tests.emplace(&test);
@@ -12995,6 +13068,7 @@ namespace Catch {
}
Totals execute() {
+ auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
Totals totals;
m_context.testGroupStarting(m_config->name(), 1, 1);
for (auto const& testCase : m_tests) {
@@ -13010,6 +13084,12 @@ namespace Catch {
totals.error = -1;
}
}
+
+ if (!invalidArgs.empty()) {
+ for (auto const& invalidArg: invalidArgs)
+ m_context.reporter().reportInvalidArguments(invalidArg);
+ }
+
m_context.testGroupEnded(m_config->name(), totals, 1, 1);
return totals;
}
@@ -14305,6 +14385,10 @@ namespace Catch {
return matches;
}
+ const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{
+ return (m_invalidArgs);
+ }
+
}
// end catch_test_spec.cpp
// start catch_test_spec_parser.cpp
@@ -14321,8 +14405,13 @@ namespace Catch {
m_substring.reserve(m_arg.size());
m_patternName.reserve(m_arg.size());
m_realPatternPos = 0;
+
for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
- visitChar( m_arg[m_pos] );
+ //if visitChar fails
+ if( !visitChar( m_arg[m_pos] ) ){
+ m_testSpec.m_invalidArgs.push_back(arg);
+ break;
+ }
endMode();
return *this;
}
@@ -14330,38 +14419,32 @@ namespace Catch {
addFilter();
return m_testSpec;
}
- void TestSpecParser::visitChar( char c ) {
+ bool TestSpecParser::visitChar( char c ) {
if( (m_mode != EscapedName) && (c == '\\') ) {
escape();
- m_substring += c;
- m_patternName += c;
- m_realPatternPos++;
- return;
+ addCharToPattern(c);
+ return true;
}else if((m_mode != EscapedName) && (c == ',') ) {
- endMode();
- addFilter();
- return;
+ return separate();
}
switch( m_mode ) {
case None:
if( processNoneChar( c ) )
- return;
+ return true;
break;
case Name:
processNameChar( c );
break;
case EscapedName:
endMode();
- m_substring += c;
- m_patternName += c;
- m_realPatternPos++;
- return;
+ addCharToPattern(c);
+ return true;
default:
case Tag:
case QuotedName:
if( processOtherChar( c ) )
- return;
+ return true;
break;
}
@@ -14370,6 +14453,7 @@ namespace Catch {
m_patternName += c;
m_realPatternPos++;
}
+ return true;
}
// Two of the processing methods return true to signal the caller to return
// without adding the given character to the current pattern strings
@@ -14462,6 +14546,20 @@ namespace Catch {
m_mode = lastMode;
}
+ bool TestSpecParser::separate() {
+ if( (m_mode==QuotedName) || (m_mode==Tag) ){
+ //invalid argument, signal failure to previous scope.
+ m_mode = None;
+ m_pos = m_arg.size();
+ m_substring.clear();
+ m_patternName.clear();
+ return false;
+ }
+ endMode();
+ addFilter();
+ return true; //success
+ }
+
TestSpec parseTestSpec( std::string const& arg ) {
return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
}
@@ -14889,7 +14987,7 @@ namespace Catch {
}
Version const& libraryVersion() {
- static Version version( 2, 10, 0, "", 0 );
+ static Version version( 2, 10, 1, "", 0 );
return version;
}
@@ -15926,6 +16024,10 @@ void ConsoleReporter::noMatchingTestCases(std::string const& spec) {
stream << "No test cases matched '" << spec << '\'' << std::endl;
}
+void ConsoleReporter::reportInvalidArguments(std::string const&arg){
+ stream << "Invalid Filter: " << arg << std::endl;
+}
+
void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
@@ -16526,6 +16628,13 @@ namespace Catch {
m_reporter->noMatchingTestCases( spec );
}
+ void ListeningReporter::reportInvalidArguments(std::string const&arg){
+ for ( auto const& listener : m_listeners ) {
+ listener->reportInvalidArguments( arg );
+ }
+ m_reporter->reportInvalidArguments( arg );
+ }
+
#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
void ListeningReporter::benchmarkPreparing( std::string const& name ) {
for (auto const& listener : m_listeners) {