Remove the ill-conceived compilation perf tests using real tests

This commit is contained in:
Martin Hořeňovský 2021-06-20 16:25:57 +02:00
parent 849002aec0
commit bf61a418cb
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
19 changed files with 2228 additions and 2276 deletions

View File

@ -2903,9 +2903,9 @@ with expansion:
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
with message: with message:
std::is_same< decltype((MatcherA() && MatcherB()) && (MatcherC() && MatcherD std::is_same< decltype( ( MatcherA() && MatcherB() ) && ( MatcherC() &&
())), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherD() ) ), Catch::Matchers::Detail:: MatchAllOfGeneric<MatcherA,
MatcherC, MatcherD> >::value MatcherB, MatcherC, MatcherD>>:: value
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( 1, ( MatcherA() && MatcherB() ) && ( MatcherC() && MatcherD() ) ) REQUIRE_THAT( 1, ( MatcherA() && MatcherB() ) && ( MatcherC() && MatcherD() ) )
@ -2943,9 +2943,9 @@ with expansion:
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
with message: with message:
std::is_same< decltype((MatcherA() || MatcherB()) || (MatcherC() || MatcherD std::is_same< decltype( ( MatcherA() || MatcherB() ) || ( MatcherC() ||
())), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherD() ) ), Catch::Matchers::Detail:: MatchAnyOfGeneric<MatcherA,
MatcherC, MatcherD> >::value MatcherB, MatcherC, MatcherD>>:: value
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( 1, ( MatcherA() || MatcherB() ) || ( MatcherC() || MatcherD() ) ) REQUIRE_THAT( 1, ( MatcherA() || MatcherB() ) || ( MatcherC() || MatcherD() ) )
@ -3005,9 +3005,9 @@ Matchers.tests.cpp:<line number>
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
with message: with message:
std::is_same< decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith std::is_same<decltype( StartsWith( "foo" ) || ( StartsWith( "bar" ) &&
("bar") && !EndsWith("foo"))), Catch::Matchers::Detail::MatchAnyOf<std:: EndsWith( "bar" ) && !EndsWith( "foo" ) ) ), Catch::Matchers::Detail::
string> >::value MatchAnyOf<std::string>>::value
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Combining only templated matchers Combining only templated matchers
@ -3037,8 +3037,8 @@ with expansion:
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
with message: with message:
std::is_same< decltype(MatcherA() || !MatcherB()), Catch::Matchers::Detail:: std::is_same< decltype( MatcherA() || !MatcherB() ), Catch::Matchers::Detail:
MatchAnyOfGeneric<MatcherA, Catch::Matchers::Detail::MatchNotOfGeneric :MatchAnyOfGeneric< MatcherA, Catch::Matchers::Detail::MatchNotOfGeneric
<MatcherB>>>::value <MatcherB>>>::value
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:

View File

@ -1,13 +0,0 @@
// Include set of usage tests multiple times - for compile-time performance testing
// (do not run)
#include "All.tests.cpp"
#include "All.tests.cpp"
#include "All.tests.cpp"
#include "All.tests.cpp"
#include "All.tests.cpp"
#include "All.tests.cpp"
#include "All.tests.cpp"
#include "All.tests.cpp"
#include "All.tests.cpp"
#include "All.tests.cpp"

View File

@ -1,13 +0,0 @@
// Include set of usage tests multiple times - for compile-time performance testing
// (do not run)
#include "10.tests.cpp"
#include "10.tests.cpp"
#include "10.tests.cpp"
#include "10.tests.cpp"
#include "10.tests.cpp"
#include "10.tests.cpp"
#include "10.tests.cpp"
#include "10.tests.cpp"
#include "10.tests.cpp"
#include "10.tests.cpp"

View File

@ -1,15 +0,0 @@
// include set of usage tests into one file for compiler performance test purposes
// This whole file can now be included multiple times in 10.tests.cpp, and *that*
// file included multiple times (in 100.tests.cpp)
// Note that the intention is only for these files to be compiled. They will
// fail at runtime due to the re-user of test case names
#include "../UsageTests/Approx.tests.cpp"
#include "../UsageTests/BDD.tests.cpp"
#include "../UsageTests/Class.tests.cpp"
#include "../UsageTests/Compilation.tests.cpp"
#include "../UsageTests/Condition.tests.cpp"
#include "../UsageTests/Exception.tests.cpp"
#include "../UsageTests/Matchers.tests.cpp"
#include "../UsageTests/Misc.tests.cpp"

View File

@ -13,12 +13,8 @@
using Catch::Approx; using Catch::Approx;
namespace { namespace ApproxTests { namespace {
static double divide(double a, double b) {
#ifndef APPROX_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
#define APPROX_TEST_HELPERS_INCLUDED
inline double divide( double a, double b ) {
return a / b; return a / b;
} }
@ -30,11 +26,10 @@ namespace { namespace ApproxTests {
explicit operator double() const { return d_; } explicit operator double() const { return d_; }
}; };
inline std::ostream& operator<<( std::ostream& os, StrongDoubleTypedef td ) { static std::ostream& operator<<(std::ostream& os, StrongDoubleTypedef td) {
return os << "StrongDoubleTypedef(" << static_cast<double>(td) << ")"; return os << "StrongDoubleTypedef(" << static_cast<double>(td) << ")";
} }
} // end unnamed namespace
#endif
using namespace Catch::literals; using namespace Catch::literals;
@ -214,5 +209,3 @@ TEST_CASE( "Comparison with explicitly convertible types", "[Approx]" )
REQUIRE(Approx(11.0) >= td); REQUIRE(Approx(11.0) >= td);
} }
}} // namespace ApproxTests

View File

@ -5,32 +5,23 @@
#include <catch2/catch_test_macros.hpp> #include <catch2/catch_test_macros.hpp>
namespace { namespace BDDTests {
#ifndef BDD_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
#define BDD_TEST_HELPERS_INCLUDED
inline bool itDoesThis() { return true; }
inline bool itDoesThat() { return true; }
namespace { namespace {
static bool itDoesThis() { return true; }
static bool itDoesThat() { return true; }
// a trivial fixture example to support SCENARIO_METHOD tests // a trivial fixture example to support SCENARIO_METHOD tests
struct Fixture { struct Fixture {
Fixture() Fixture(): d_counter( 0 ) {}
: d_counter(0) {
}
int counter() { int counter() { return d_counter++; }
return d_counter++;
}
int d_counter; int d_counter;
}; };
} }
#endif
SCENARIO("Do that thing with the thing", "[Tags]") { SCENARIO("Do that thing with the thing", "[Tags]") {
GIVEN("This stuff exists") { GIVEN("This stuff exists") {
@ -41,14 +32,17 @@ namespace { namespace BDDTests {
// do this // do this
THEN("it should do this") { THEN("it should do this") {
REQUIRE(itDoesThis()); REQUIRE(itDoesThis());
AND_THEN("do that")REQUIRE(itDoesThat()); AND_THEN("do that") {
REQUIRE(itDoesThat());
}
} }
} }
} }
} }
} }
SCENARIO("Vector resizing affects size and capacity", "[vector][bdd][size][capacity]") { SCENARIO( "Vector resizing affects size and capacity",
"[vector][bdd][size][capacity]" ) {
GIVEN( "an empty vector" ) { GIVEN( "an empty vector" ) {
std::vector<int> v; std::vector<int> v;
REQUIRE( v.size() == 0 ); REQUIRE( v.size() == 0 );
@ -61,7 +55,8 @@ namespace { namespace BDDTests {
AND_WHEN( "it is made smaller again" ) { AND_WHEN( "it is made smaller again" ) {
v.resize( 5 ); v.resize( 5 );
THEN("the size goes down but the capacity stays the same") { THEN(
"the size goes down but the capacity stays the same" ) {
REQUIRE( v.size() == 5 ); REQUIRE( v.size() == 5 );
REQUIRE( v.capacity() >= 10 ); REQUIRE( v.capacity() >= 10 );
} }
@ -83,10 +78,13 @@ namespace { namespace BDDTests {
"[very long tags][lots][long][tags][verbose]" "[very long tags][lots][long][tags][verbose]"
"[one very long tag name that should cause line wrapping writing out using the list command]" "[one very long tag name that should cause line wrapping writing out using the list command]"
"[anotherReallyLongTagNameButThisOneHasNoObviousWrapPointsSoShouldSplitWithinAWordUsingADashCharacter]") { "[anotherReallyLongTagNameButThisOneHasNoObviousWrapPointsSoShouldSplitWithinAWordUsingADashCharacter]") {
GIVEN("A section name that is so long that it cannot fit in a single console width")WHEN( GIVEN("A section name that is so long that it cannot fit in a single console width") {
"The test headers are printed as part of the normal running of the scenario")THEN( WHEN("The test headers are printed as part of the normal running of the scenario") {
"The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent")SUCCEED( THEN("The, deliberately very long and overly verbose (you see what I did there?) section names must wrap, along with an indent") {
"boo!"); SUCCEED("boo!");
}
}
}
} }
SCENARIO_METHOD(Fixture, SCENARIO_METHOD(Fixture,
@ -103,5 +101,3 @@ namespace { namespace BDDTests {
} }
} }
} }
}} // namespace BDDtests

View File

@ -7,68 +7,47 @@
#include <catch2/catch_template_test_macros.hpp> #include <catch2/catch_template_test_macros.hpp>
#include <array> #include <array>
namespace{ namespace ClassTests { namespace {
#ifndef CLASS_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU class TestClass {
#define CLASS_TEST_HELPERS_INCLUDED
class TestClass
{
std::string s; std::string s;
public: public:
TestClass() TestClass(): s( "hello" ) {}
: s( "hello" )
{}
void succeedingCase() void succeedingCase() { REQUIRE( s == "hello" ); }
{ void failingCase() { REQUIRE( s == "world" ); }
REQUIRE( s == "hello" );
}
void failingCase()
{
REQUIRE( s == "world" );
}
}; };
struct Fixture struct Fixture {
{
Fixture(): m_a( 1 ) {} Fixture(): m_a( 1 ) {}
int m_a; int m_a;
}; };
template< typename T > template <typename T> struct Template_Fixture {
struct Template_Fixture {
Template_Fixture(): m_a( 1 ) {} Template_Fixture(): m_a( 1 ) {}
T m_a; T m_a;
}; };
template<typename T> template <typename T> struct Template_Fixture_2 {
struct Template_Fixture_2 {
Template_Fixture_2() {} Template_Fixture_2() {}
T m_a; T m_a;
}; };
template< typename T> template <typename T> struct Template_Foo {
struct Template_Foo {
size_t size() { return 0; } size_t size() { return 0; }
}; };
template< typename T, size_t V> template <typename T, size_t V> struct Template_Foo_2 {
struct Template_Foo_2 {
size_t size() { return V; } size_t size() { return V; }
}; };
template <int V> template <int V> struct Nttp_Fixture { int value = V; };
struct Nttp_Fixture{
int value = V;
};
#endif
} // end unnamed namespace
METHOD_AS_TEST_CASE( TestClass::succeedingCase, "A METHOD_AS_TEST_CASE based test run that succeeds", "[class]" ) METHOD_AS_TEST_CASE( TestClass::succeedingCase, "A METHOD_AS_TEST_CASE based test run that succeeds", "[class]" )
METHOD_AS_TEST_CASE( TestClass::failingCase, "A METHOD_AS_TEST_CASE based test run that fails", "[.][class][failing]" ) METHOD_AS_TEST_CASE( TestClass::failingCase, "A METHOD_AS_TEST_CASE based test run that fails", "[.][class][failing]" )
@ -129,7 +108,3 @@ namespace Inner
REQUIRE(Template_Fixture_2<TestType>{}.m_a.size() < 2); REQUIRE(Template_Fixture_2<TestType>{}.m_a.size() < 2);
} }
} }
}} // namespace ClassTests

View File

@ -33,11 +33,6 @@ std::ostream& operator<<(std::ostream& out, foo::helper_1403 const&) {
#include <cstring> #include <cstring>
namespace { namespace CompilationTests {
#ifndef COMPILATION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
#define COMPILATION_TEST_HELPERS_INCLUDED
// Comparison operators can return non-booleans. // Comparison operators can return non-booleans.
// This is unusual, but should be supported. // This is unusual, but should be supported.
struct logic_t { struct logic_t {
@ -51,16 +46,6 @@ namespace { namespace CompilationTests {
}; };
// This is a minimal example for an issue we have found in 1.7.0
struct foo {
int i;
};
template<typename T>
bool operator==(const T &val, foo f) {
return val == f.i;
}
void throws_int(bool b) { void throws_int(bool b) {
if (b) { if (b) {
throw 1; throw 1;
@ -79,8 +64,7 @@ namespace { namespace CompilationTests {
return true; return true;
} }
struct A { struct A {};
};
std::ostream &operator<<(std::ostream &o, const A &) { return o << 0; } std::ostream &operator<<(std::ostream &o, const A &) { return o << 0; }
@ -109,10 +93,18 @@ namespace { namespace CompilationTests {
template <typename, typename> template <typename, typename>
struct Fixture_1245 {}; struct Fixture_1245 {};
#endif // This is a minimal example for an issue we have found in 1.7.0
struct dummy_809 {
int i;
};
template<typename T>
bool operator==(const T& val, dummy_809 f) {
return val == f.i;
}
TEST_CASE("#809") { TEST_CASE("#809") {
foo f; dummy_809 f;
f.i = 42; f.i = 42;
REQUIRE(42 == f); REQUIRE(42 == f);
} }
@ -129,8 +121,6 @@ namespace { namespace CompilationTests {
// Test containing example where original stream insertable check breaks compilation // Test containing example where original stream insertable check breaks compilation
TEST_CASE("#872") { TEST_CASE("#872") {
A dummy; A dummy;
CAPTURE(dummy); CAPTURE(dummy);
@ -214,7 +204,8 @@ namespace { namespace CompilationTests {
#pragma warning(pop) #pragma warning(pop)
#endif #endif
TEST_CASE("#1319: Sections can have description (even if it is not saved", "[compilation]") { TEST_CASE( "#1319: Sections can have description (even if it is not saved",
"[compilation]" ) {
SECTION( "SectionName", "This is a long form section description" ) { SECTION( "SectionName", "This is a long form section description" ) {
SUCCEED(); SUCCEED();
} }
@ -224,8 +215,6 @@ namespace { namespace CompilationTests {
REQUIRE([]() { return true; }()); REQUIRE([]() { return true; }());
} }
}} // namespace CompilationTests
namespace { namespace {
struct HasBitOperators { struct HasBitOperators {
int value; int value;

View File

@ -20,10 +20,7 @@ using Catch::Approx;
#include <limits> #include <limits>
#include <cstdint> #include <cstdint>
namespace { namespace ConditionTests { namespace {
#ifndef CONDITION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
#define CONDITION_TEST_HELPERS_INCLUDED
struct TestData { struct TestData {
int int_seven = 7; int int_seven = 7;
@ -41,10 +38,10 @@ struct TestDef {
} }
}; };
inline const char* returnsConstNull(){ return nullptr; } static const char* returnsConstNull() { return nullptr; }
inline char* returnsNull(){ return nullptr; } static char* returnsNull() { return nullptr; }
#endif } // end unnamed namespace
// The "failing" tests all use the CHECK macro, which continues if the specific test fails. // The "failing" tests all use the CHECK macro, which continues if the specific test fails.
// This allows us to see all results, even if an earlier check fails // This allows us to see all results, even if an earlier check fails
@ -330,5 +327,3 @@ TEST_CASE( "'Not' checks that should fail", "[.][failing]" )
CHECK( !(1 == 1) ); CHECK( !(1 == 1) );
CHECK_FALSE( 1 == 1 ); CHECK_FALSE( 1 == 1 );
} }
}} // namespace ConditionTests

View File

@ -20,10 +20,7 @@
#pragma clang diagnostic ignored "-Wunreachable-code" #pragma clang diagnostic ignored "-Wunreachable-code"
#endif #endif
namespace { namespace ExceptionTests { namespace {
#ifndef EXCEPTION_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU
#define EXCEPTION_TEST_HELPERS_INCLUDED
int thisThrows() { int thisThrows() {
throw std::domain_error("expected exception"); throw std::domain_error("expected exception");
@ -37,8 +34,7 @@ int thisDoesntThrow() {
class CustomException { class CustomException {
public: public:
explicit CustomException(const std::string& msg) explicit CustomException(const std::string& msg)
: m_msg( msg ) : m_msg(msg) {}
{}
std::string getMessage() const { std::string getMessage() const {
return m_msg; return m_msg;
@ -51,8 +47,7 @@ private:
class CustomStdException : public std::exception { class CustomStdException : public std::exception {
public: public:
explicit CustomStdException(const std::string& msg) explicit CustomStdException(const std::string& msg)
: m_msg( msg ) : m_msg(msg) {}
{}
~CustomStdException() noexcept override {} ~CustomStdException() noexcept override {}
std::string getMessage() const { std::string getMessage() const {
@ -67,7 +62,7 @@ private:
throw CustomException("custom exception - not std"); throw CustomException("custom exception - not std");
} }
#endif }
TEST_CASE( "When checked exceptions are thrown they can be expected or unexpected", "[!throws]" ) { TEST_CASE( "When checked exceptions are thrown they can be expected or unexpected", "[!throws]" ) {
REQUIRE_THROWS_AS( thisThrows(), std::domain_error ); REQUIRE_THROWS_AS( thisThrows(), std::domain_error );
@ -198,8 +193,6 @@ TEST_CASE( "#748 - captures with unexpected exceptions", "[.][failing][!throws][
} }
} }
}} // namespace ExceptionTests
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif

View File

@ -12,6 +12,7 @@
#include <catch2/matchers/catch_matchers_templated.hpp> #include <catch2/matchers/catch_matchers_templated.hpp>
#include <algorithm> #include <algorithm>
#include <exception>
#include <cmath> #include <cmath>
#include <list> #include <list>
#include <sstream> #include <sstream>
@ -22,29 +23,24 @@
# pragma clang diagnostic ignored "-Wpadded" # pragma clang diagnostic ignored "-Wpadded"
#endif #endif
namespace { namespace MatchersTests { namespace {
#ifndef MATCHERS_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU static const char* testStringForMatching() {
#define MATCHERS_TEST_HELPERS_INCLUDED
inline const char *testStringForMatching() {
return "this string contains 'abc' as a substring"; return "this string contains 'abc' as a substring";
} }
inline const char *testStringForMatching2() { static const char* testStringForMatching2() {
return "some completely different text that contains one common word"; return "some completely different text that contains one common word";
} }
inline bool alwaysTrue(int) { return true; } static bool alwaysTrue( int ) { return true; }
inline bool alwaysFalse(int) { return false; } static bool alwaysFalse( int ) { return false; }
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable:4702) // Unreachable code -- MSVC 19 (VS 2015) sees right through the indirection # pragma warning( disable : 4702 ) // Unreachable code -- MSVC 19 (VS 2015)
// sees right through the indirection
#endif #endif
#include <exception>
struct SpecialException : std::exception { struct SpecialException : std::exception {
SpecialException( int i_ ): i( i_ ) {} SpecialException( int i_ ): i( i_ ) {}
@ -61,25 +57,22 @@ namespace { namespace MatchersTests {
} }
}; };
void doesNotThrow() {} static void doesNotThrow() {}
[[noreturn]] [[noreturn]] static void throwsSpecialException( int i ) {
void throwsSpecialException(int i) {
throw SpecialException{ i }; throw SpecialException{ i };
} }
[[noreturn]] [[noreturn]] static void throwsAsInt( int i ) { throw i; }
void throwsAsInt(int i) {
throw i;
}
[[noreturn]] [[noreturn]] static void throwsDerivedException() {
void throwsDerivedException() {
throw DerivedException{}; throw DerivedException{};
} }
class ExceptionMatcher : public Catch::Matchers::MatcherBase<SpecialException> { class ExceptionMatcher
: public Catch::Matchers::MatcherBase<SpecialException> {
int m_expected; int m_expected;
public: public:
ExceptionMatcher( int i ): m_expected( i ) {} ExceptionMatcher( int i ): m_expected( i ) {}
@ -94,121 +87,133 @@ namespace { namespace MatchersTests {
} }
}; };
#endif
using namespace Catch::Matchers; using namespace Catch::Matchers;
#ifdef __DJGPP__ #ifdef __DJGPP__
float nextafter(float from, float to) static float nextafter( float from, float to ) {
{
return ::nextafterf( from, to ); return ::nextafterf( from, to );
} }
double nextafter(double from, double to) static double nextafter( double from, double to ) {
{
return ::nextafter( from, to ); return ::nextafter( from, to );
} }
#else #else
using std::nextafter; using std::nextafter;
#endif #endif
} // end unnamed namespace
TEST_CASE( "String matchers", "[matchers]" ) { TEST_CASE( "String matchers", "[matchers]" ) {
REQUIRE_THAT( testStringForMatching(), Contains( "string" ) ); REQUIRE_THAT( testStringForMatching(), Contains( "string" ) );
REQUIRE_THAT(testStringForMatching(), Contains("string", Catch::CaseSensitive::No)); REQUIRE_THAT( testStringForMatching(),
Contains( "string", Catch::CaseSensitive::No ) );
CHECK_THAT( testStringForMatching(), Contains( "abc" ) ); CHECK_THAT( testStringForMatching(), Contains( "abc" ) );
CHECK_THAT(testStringForMatching(), Contains("aBC", Catch::CaseSensitive::No)); CHECK_THAT( testStringForMatching(),
Contains( "aBC", Catch::CaseSensitive::No ) );
CHECK_THAT( testStringForMatching(), StartsWith( "this" ) ); CHECK_THAT( testStringForMatching(), StartsWith( "this" ) );
CHECK_THAT(testStringForMatching(), StartsWith("THIS", Catch::CaseSensitive::No)); CHECK_THAT( testStringForMatching(),
StartsWith( "THIS", Catch::CaseSensitive::No ) );
CHECK_THAT( testStringForMatching(), EndsWith( "substring" ) ); CHECK_THAT( testStringForMatching(), EndsWith( "substring" ) );
CHECK_THAT(testStringForMatching(), EndsWith(" SuBsTrInG", Catch::CaseSensitive::No)); CHECK_THAT( testStringForMatching(),
EndsWith( " SuBsTrInG", Catch::CaseSensitive::No ) );
} }
TEST_CASE( "Contains string matcher", "[.][failing][matchers]" ) { TEST_CASE( "Contains string matcher", "[.][failing][matchers]" ) {
CHECK_THAT(testStringForMatching(), Contains("not there", Catch::CaseSensitive::No)); CHECK_THAT( testStringForMatching(),
Contains( "not there", Catch::CaseSensitive::No ) );
CHECK_THAT( testStringForMatching(), Contains( "STRING" ) ); CHECK_THAT( testStringForMatching(), Contains( "STRING" ) );
} }
TEST_CASE( "StartsWith string matcher", "[.][failing][matchers]" ) { TEST_CASE( "StartsWith string matcher", "[.][failing][matchers]" ) {
CHECK_THAT( testStringForMatching(), StartsWith( "This String" ) ); CHECK_THAT( testStringForMatching(), StartsWith( "This String" ) );
CHECK_THAT(testStringForMatching(), StartsWith("string", Catch::CaseSensitive::No)); CHECK_THAT( testStringForMatching(),
StartsWith( "string", Catch::CaseSensitive::No ) );
} }
TEST_CASE( "EndsWith string matcher", "[.][failing][matchers]" ) { TEST_CASE( "EndsWith string matcher", "[.][failing][matchers]" ) {
CHECK_THAT( testStringForMatching(), EndsWith( "Substring" ) ); CHECK_THAT( testStringForMatching(), EndsWith( "Substring" ) );
CHECK_THAT(testStringForMatching(), EndsWith("this", Catch::CaseSensitive::No)); CHECK_THAT( testStringForMatching(),
EndsWith( "this", Catch::CaseSensitive::No ) );
} }
TEST_CASE( "Equals string matcher", "[.][failing][matchers]" ) { TEST_CASE( "Equals string matcher", "[.][failing][matchers]" ) {
CHECK_THAT(testStringForMatching(), Equals("this string contains 'ABC' as a substring")); CHECK_THAT( testStringForMatching(),
CHECK_THAT(testStringForMatching(), Equals("something else", Catch::CaseSensitive::No)); Equals( "this string contains 'ABC' as a substring" ) );
CHECK_THAT( testStringForMatching(),
Equals( "something else", Catch::CaseSensitive::No ) );
} }
TEST_CASE( "Equals", "[matchers]" ) { TEST_CASE( "Equals", "[matchers]" ) {
CHECK_THAT(testStringForMatching(), Equals("this string contains 'abc' as a substring"));
CHECK_THAT( testStringForMatching(), CHECK_THAT( testStringForMatching(),
Equals("this string contains 'ABC' as a substring", Catch::CaseSensitive::No)); Equals( "this string contains 'abc' as a substring" ) );
CHECK_THAT( testStringForMatching(),
Equals( "this string contains 'ABC' as a substring",
Catch::CaseSensitive::No ) );
} }
// <regex> does not work in libstdc++ 4.8, so we have to enable these tests only when they TEST_CASE( "Regex string matcher -- libstdc++-4.8 workaround",
// are expected to pass and cannot have them in baselines "[matchers][approvals]" ) {
TEST_CASE("Regex string matcher -- libstdc++-4.8 workaround", "[matchers][approvals]") { // DJGPP has similar problem with its regex support as libstdc++ 4.8
// This is fiiiine
// Taken from an answer at
// https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions
#if (!defined(__GNUC__)) || \
(__cplusplus >= 201103L && \
(!defined(__GLIBCXX__) || (__cplusplus >= 201402L) || \
(defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \
defined(_GLIBCXX_REGEX_STATE_LIMIT) || \
(defined(_GLIBCXX_RELEASE) && \
_GLIBCXX_RELEASE > 4))))
// DJGPP meets the above condition but <regex> does not work properly anyway
#ifndef __DJGPP__ #ifndef __DJGPP__
REQUIRE_THAT(testStringForMatching(), Matches("this string contains 'abc' as a substring"));
REQUIRE_THAT( testStringForMatching(), REQUIRE_THAT( testStringForMatching(),
Matches("this string CONTAINS 'abc' as a substring", Catch::CaseSensitive::No)); Matches( "this string contains 'abc' as a substring" ) );
REQUIRE_THAT(testStringForMatching(), Matches("^this string contains 'abc' as a substring$")); REQUIRE_THAT( testStringForMatching(),
Matches( "this string CONTAINS 'abc' as a substring",
Catch::CaseSensitive::No ) );
REQUIRE_THAT( testStringForMatching(),
Matches( "^this string contains 'abc' as a substring$" ) );
REQUIRE_THAT( testStringForMatching(), Matches( "^.* 'abc' .*$" ) ); REQUIRE_THAT( testStringForMatching(), Matches( "^.* 'abc' .*$" ) );
REQUIRE_THAT(testStringForMatching(), Matches("^.* 'ABC' .*$", Catch::CaseSensitive::No)); REQUIRE_THAT( testStringForMatching(),
Matches( "^.* 'ABC' .*$", Catch::CaseSensitive::No ) );
#endif #endif
#endif REQUIRE_THAT( testStringForMatching2(),
!Matches( "this string contains 'abc' as a substring" ) );
REQUIRE_THAT(testStringForMatching2(), !Matches("this string contains 'abc' as a substring"));
} }
TEST_CASE( "Regex string matcher", "[matchers][.failing]" ) { TEST_CASE( "Regex string matcher", "[matchers][.failing]" ) {
CHECK_THAT(testStringForMatching(), Matches("this STRING contains 'abc' as a substring"));
CHECK_THAT(testStringForMatching(), Matches("contains 'abc' as a substring"));
CHECK_THAT(testStringForMatching(), Matches("this string contains 'abc' as a"));
}
TEST_CASE("Matchers can be (AllOf) composed with the && operator", "[matchers][operators][operator&&]") {
CHECK_THAT( testStringForMatching(), CHECK_THAT( testStringForMatching(),
Contains("string") && Matches( "this STRING contains 'abc' as a substring" ) );
Contains("abc") && CHECK_THAT( testStringForMatching(),
Contains("substring") && Matches( "contains 'abc' as a substring" ) );
Contains("contains")); CHECK_THAT( testStringForMatching(),
Matches( "this string contains 'abc' as a" ) );
} }
TEST_CASE("Matchers can be (AnyOf) composed with the || operator", "[matchers][operators][operator||]") { TEST_CASE( "Matchers can be (AllOf) composed with the && operator",
CHECK_THAT(testStringForMatching(), Contains("string") || Contains("different") || Contains("random")); "[matchers][operators][operator&&]" ) {
CHECK_THAT(testStringForMatching2(), Contains("string") || Contains("different") || Contains("random")); CHECK_THAT( testStringForMatching(),
Contains( "string" ) && Contains( "abc" ) &&
Contains( "substring" ) && Contains( "contains" ) );
} }
TEST_CASE("Matchers can be composed with both && and ||", "[matchers][operators][operator||][operator&&]") { TEST_CASE( "Matchers can be (AnyOf) composed with the || operator",
CHECK_THAT(testStringForMatching(), (Contains("string") || Contains("different")) && Contains("substring")); "[matchers][operators][operator||]" ) {
CHECK_THAT( testStringForMatching(),
Contains( "string" ) || Contains( "different" ) ||
Contains( "random" ) );
CHECK_THAT( testStringForMatching2(),
Contains( "string" ) || Contains( "different" ) ||
Contains( "random" ) );
}
TEST_CASE( "Matchers can be composed with both && and ||",
"[matchers][operators][operator||][operator&&]" ) {
CHECK_THAT( testStringForMatching(),
( Contains( "string" ) || Contains( "different" ) ) &&
Contains( "substring" ) );
} }
TEST_CASE( "Matchers can be composed with both && and || - failing", TEST_CASE( "Matchers can be composed with both && and || - failing",
"[matchers][operators][operator||][operator&&][.failing]" ) { "[matchers][operators][operator||][operator&&][.failing]" ) {
CHECK_THAT(testStringForMatching(), (Contains("string") || Contains("different")) && Contains("random")); CHECK_THAT( testStringForMatching(),
( Contains( "string" ) || Contains( "different" ) ) &&
Contains( "random" ) );
} }
TEST_CASE("Matchers can be negated (Not) with the ! operator", "[matchers][operators][not]") { TEST_CASE( "Matchers can be negated (Not) with the ! operator",
"[matchers][operators][not]" ) {
CHECK_THAT( testStringForMatching(), !Contains( "different" ) ); CHECK_THAT( testStringForMatching(), !Contains( "different" ) );
} }
@ -217,9 +222,7 @@ namespace { namespace MatchersTests {
CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ); CHECK_THAT( testStringForMatching(), !Contains( "substring" ) );
} }
template<typename T> template <typename T> struct CustomAllocator : private std::allocator<T> {
struct CustomAllocator : private std::allocator<T>
{
using size_type = size_t; using size_type = size_t;
using difference_type = ptrdiff_t; using difference_type = ptrdiff_t;
using pointer = T*; using pointer = T*;
@ -228,20 +231,17 @@ namespace { namespace MatchersTests {
using const_reference = const T&; using const_reference = const T&;
using value_type = T; using value_type = T;
template<typename U> template <typename U> struct rebind { using other = CustomAllocator<U>; };
struct rebind
{ using other = CustomAllocator<U>; };
using propagate_on_container_move_assignment = std::true_type; using propagate_on_container_move_assignment = std::true_type;
using is_always_equal = std::true_type; using is_always_equal = std::true_type;
CustomAllocator() = default; CustomAllocator() = default;
CustomAllocator(const CustomAllocator& other) CustomAllocator( const CustomAllocator& other ):
: std::allocator<T>(other) { } std::allocator<T>( other ) {}
template<typename U> template <typename U> CustomAllocator( const CustomAllocator<U>& ) {}
CustomAllocator(const CustomAllocator<U>&) { }
~CustomAllocator() = default; ~CustomAllocator() = default;
@ -288,7 +288,9 @@ namespace { namespace MatchersTests {
SECTION( "Contains (vector)" ) { SECTION( "Contains (vector)" ) {
CHECK_THAT( v, Contains( v2 ) ); CHECK_THAT( v, Contains( v2 ) );
CHECK_THAT( v, Contains<int>( { 1, 2 } ) ); CHECK_THAT( v, Contains<int>( { 1, 2 } ) );
CHECK_THAT(v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2))); CHECK_THAT( v5,
( Contains<int, std::allocator<int>, CustomAllocator<int>>(
v2 ) ) );
v2.push_back( 3 ); // now exactly matches v2.push_back( 3 ); // now exactly matches
CHECK_THAT( v, Contains( v2 ) ); CHECK_THAT( v, Contains( v2 ) );
@ -296,7 +298,9 @@ namespace { namespace MatchersTests {
CHECK_THAT( v, Contains( empty ) ); CHECK_THAT( v, Contains( empty ) );
CHECK_THAT( empty, Contains( empty ) ); CHECK_THAT( empty, Contains( empty ) );
CHECK_THAT(v5, (Contains<int, std::allocator<int>, CustomAllocator<int>>(v2))); CHECK_THAT( v5,
( Contains<int, std::allocator<int>, CustomAllocator<int>>(
v2 ) ) );
CHECK_THAT( v5, Contains( v6 ) ); CHECK_THAT( v5, Contains( v6 ) );
} }
SECTION( "Contains (element), composed" ) { SECTION( "Contains (element), composed" ) {
@ -315,7 +319,9 @@ namespace { namespace MatchersTests {
v2.push_back( 3 ); v2.push_back( 3 );
CHECK_THAT( v, Equals( v2 ) ); CHECK_THAT( v, Equals( v2 ) );
CHECK_THAT(v5, (Equals<int, std::allocator<int>, CustomAllocator<int>>(v2))); CHECK_THAT(
v5,
( Equals<int, std::allocator<int>, CustomAllocator<int>>( v2 ) ) );
v6.push_back( 3 ); v6.push_back( 3 );
CHECK_THAT( v5, Equals( v6 ) ); CHECK_THAT( v5, Equals( v6 ) );
@ -332,7 +338,10 @@ namespace { namespace MatchersTests {
std::reverse( begin( permuted ), end( permuted ) ); std::reverse( begin( permuted ), end( permuted ) );
REQUIRE_THAT( permuted, UnorderedEquals( v ) ); REQUIRE_THAT( permuted, UnorderedEquals( v ) );
CHECK_THAT(v5, (UnorderedEquals<int, std::allocator<int>, CustomAllocator<int>>(permuted))); CHECK_THAT(
v5,
( UnorderedEquals<int, std::allocator<int>, CustomAllocator<int>>(
permuted ) ) );
auto v5_permuted = v5; auto v5_permuted = v5;
std::next_permutation( begin( v5_permuted ), end( v5_permuted ) ); std::next_permutation( begin( v5_permuted ), end( v5_permuted ) );
@ -393,23 +402,35 @@ namespace { namespace MatchersTests {
} }
} }
TEST_CASE("Exception matchers that succeed", "[matchers][exceptions][!throws]") { TEST_CASE( "Exception matchers that succeed",
CHECK_THROWS_MATCHES(throwsSpecialException(1), SpecialException, ExceptionMatcher{1}); "[matchers][exceptions][!throws]" ) {
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, ExceptionMatcher{2}); CHECK_THROWS_MATCHES(
throwsSpecialException( 1 ), SpecialException, ExceptionMatcher{ 1 } );
REQUIRE_THROWS_MATCHES(
throwsSpecialException( 2 ), SpecialException, ExceptionMatcher{ 2 } );
} }
TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.failing]") { TEST_CASE( "Exception matchers that fail",
"[matchers][exceptions][!throws][.failing]" ) {
SECTION( "No exception" ) { SECTION( "No exception" ) {
CHECK_THROWS_MATCHES(doesNotThrow(), SpecialException, ExceptionMatcher{1}); CHECK_THROWS_MATCHES(
REQUIRE_THROWS_MATCHES(doesNotThrow(), SpecialException, ExceptionMatcher{1}); doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } );
REQUIRE_THROWS_MATCHES(
doesNotThrow(), SpecialException, ExceptionMatcher{ 1 } );
} }
SECTION( "Type mismatch" ) { SECTION( "Type mismatch" ) {
CHECK_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{1}); CHECK_THROWS_MATCHES(
REQUIRE_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{1}); throwsAsInt( 1 ), SpecialException, ExceptionMatcher{ 1 } );
REQUIRE_THROWS_MATCHES(
throwsAsInt( 1 ), SpecialException, ExceptionMatcher{ 1 } );
} }
SECTION( "Contents are wrong" ) { SECTION( "Contents are wrong" ) {
CHECK_THROWS_MATCHES(throwsSpecialException(3), SpecialException, ExceptionMatcher{1}); CHECK_THROWS_MATCHES( throwsSpecialException( 3 ),
REQUIRE_THROWS_MATCHES(throwsSpecialException(4), SpecialException, ExceptionMatcher{1}); SpecialException,
ExceptionMatcher{ 1 } );
REQUIRE_THROWS_MATCHES( throwsSpecialException( 4 ),
SpecialException,
ExceptionMatcher{ 1 } );
} }
} }
@ -456,14 +477,16 @@ namespace { namespace MatchersTests {
SECTION( "Composed" ) { SECTION( "Composed" ) {
REQUIRE_THAT( 1.f, WithinAbs( 1.f, 0.5 ) || WithinULP( 1.f, 1 ) ); REQUIRE_THAT( 1.f, WithinAbs( 1.f, 0.5 ) || WithinULP( 1.f, 1 ) );
REQUIRE_THAT( 1.f, WithinAbs( 2.f, 0.5 ) || WithinULP( 1.f, 0 ) ); REQUIRE_THAT( 1.f, WithinAbs( 2.f, 0.5 ) || WithinULP( 1.f, 0 ) );
REQUIRE_THAT(0.0001f, WithinAbs(0.f, 0.001f) || WithinRel(0.f, 0.1f)); REQUIRE_THAT( 0.0001f,
WithinAbs( 0.f, 0.001f ) || WithinRel( 0.f, 0.1f ) );
} }
SECTION( "Constructor validation" ) { SECTION( "Constructor validation" ) {
REQUIRE_NOTHROW( WithinAbs( 1.f, 0.f ) ); REQUIRE_NOTHROW( WithinAbs( 1.f, 0.f ) );
REQUIRE_THROWS_AS( WithinAbs( 1.f, -1.f ), std::domain_error ); REQUIRE_THROWS_AS( WithinAbs( 1.f, -1.f ), std::domain_error );
REQUIRE_NOTHROW( WithinULP( 1.f, 0 ) ); REQUIRE_NOTHROW( WithinULP( 1.f, 0 ) );
REQUIRE_THROWS_AS(WithinULP(1.f, static_cast<uint64_t>(-1)), std::domain_error); REQUIRE_THROWS_AS( WithinULP( 1.f, static_cast<uint64_t>( -1 ) ),
std::domain_error );
REQUIRE_NOTHROW( WithinRel( 1.f, 0.f ) ); REQUIRE_NOTHROW( WithinRel( 1.f, 0.f ) );
REQUIRE_THROWS_AS( WithinRel( 1.f, -0.2f ), std::domain_error ); REQUIRE_THROWS_AS( WithinRel( 1.f, -0.2f ), std::domain_error );
@ -526,7 +549,8 @@ namespace { namespace MatchersTests {
} }
} }
TEST_CASE("Floating point matchers that are problematic in approvals", "[approvals][matchers][floating-point]") { TEST_CASE( "Floating point matchers that are problematic in approvals",
"[approvals][matchers][floating-point]" ) {
REQUIRE_THAT( NAN, !WithinAbs( NAN, 0 ) ); REQUIRE_THAT( NAN, !WithinAbs( NAN, 0 ) );
REQUIRE_THAT( NAN, !( WithinAbs( NAN, 100 ) || WithinULP( NAN, 123 ) ) ); REQUIRE_THAT( NAN, !( WithinAbs( NAN, 100 ) || WithinULP( NAN, 123 ) ) );
REQUIRE_THAT( NAN, !WithinULP( NAN, 123 ) ); REQUIRE_THAT( NAN, !WithinULP( NAN, 123 ) );
@ -547,15 +571,16 @@ namespace { namespace MatchersTests {
SECTION( "Lambdas + different type" ) { SECTION( "Lambdas + different type" ) {
REQUIRE_THAT( "Hello olleH", REQUIRE_THAT( "Hello olleH",
Predicate<std::string>( Predicate<std::string>(
[] (std::string const& str) -> bool { return str.front() == str.back(); }, []( std::string const& str ) -> bool {
"First and last character should be equal") return str.front() == str.back();
); },
"First and last character should be equal" ) );
REQUIRE_THAT("This wouldn't pass", REQUIRE_THAT(
!Predicate<std::string>( "This wouldn't pass",
[] (std::string const& str) -> bool { return str.front() == str.back(); } !Predicate<std::string>( []( std::string const& str ) -> bool {
) return str.front() == str.back();
); } ) );
} }
} }
@ -568,8 +593,11 @@ namespace { namespace MatchersTests {
CHECK_THAT( actual, !UnorderedEquals( expected ) ); CHECK_THAT( actual, !UnorderedEquals( expected ) );
} }
TEST_CASE("Predicate matcher can accept const char*", "[matchers][compilation]") { TEST_CASE( "Predicate matcher can accept const char*",
REQUIRE_THAT("foo", Predicate<const char*>([] (const char* const&) { return true; })); "[matchers][compilation]" ) {
REQUIRE_THAT( "foo", Predicate<const char*>( []( const char* const& ) {
return true;
} ) );
} }
TEST_CASE( "Vector Approx matcher", "[matchers][approx][vector]" ) { TEST_CASE( "Vector Approx matcher", "[matchers][approx][vector]" ) {
@ -599,7 +627,8 @@ namespace { namespace MatchersTests {
} }
} }
TEST_CASE("Vector Approx matcher -- failing", "[matchers][approx][vector][.failing]") { TEST_CASE( "Vector Approx matcher -- failing",
"[matchers][approx][vector][.failing]" ) {
using Catch::Matchers::Approx; using Catch::Matchers::Approx;
SECTION( "Empty and non empty vectors are not approx equal" ) { SECTION( "Empty and non empty vectors are not approx equal" ) {
std::vector<double> empty, t1( { 1, 2 } ); std::vector<double> empty, t1( { 1, 2 } );
@ -612,10 +641,18 @@ namespace { namespace MatchersTests {
} }
TEST_CASE( "Exceptions matchers", "[matchers][exceptions][!throws]" ) { TEST_CASE( "Exceptions matchers", "[matchers][exceptions][!throws]" ) {
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, Message("DerivedException::what")); REQUIRE_THROWS_MATCHES( throwsDerivedException(),
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, !Message("derivedexception::what")); DerivedException,
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, !Message("DerivedException::what")); Message( "DerivedException::what" ) );
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, Message("SpecialException::what")); REQUIRE_THROWS_MATCHES( throwsDerivedException(),
DerivedException,
!Message( "derivedexception::what" ) );
REQUIRE_THROWS_MATCHES( throwsSpecialException( 2 ),
SpecialException,
!Message( "DerivedException::what" ) );
REQUIRE_THROWS_MATCHES( throwsSpecialException( 2 ),
SpecialException,
Message( "SpecialException::what" ) );
} }
struct CheckedTestingMatcher : Catch::Matchers::MatcherBase<int> { struct CheckedTestingMatcher : Catch::Matchers::MatcherBase<int> {
@ -627,7 +664,9 @@ namespace { namespace MatchersTests {
return matchSucceeds; return matchSucceeds;
} }
std::string describe() const override { std::string describe() const override {
return "CheckedTestingMatcher set to " + (matchSucceeds ? std::string("succeed") : std::string("fail")); return "CheckedTestingMatcher set to " +
( matchSucceeds ? std::string( "succeed" )
: std::string( "fail" ) );
} }
}; };
@ -668,11 +707,14 @@ namespace { namespace MatchersTests {
return matchSucceeds; return matchSucceeds;
} }
std::string describe() const override { std::string describe() const override {
return "CheckedTestingGenericMatcher set to " + (matchSucceeds ? std::string("succeed") : std::string("fail")); return "CheckedTestingGenericMatcher set to " +
( matchSucceeds ? std::string( "succeed" )
: std::string( "fail" ) );
} }
}; };
TEST_CASE("Composed generic matchers shortcircuit", "[matchers][composed][generic]") { TEST_CASE( "Composed generic matchers shortcircuit",
"[matchers][composed][generic]" ) {
// Check that if first returns false, second is not touched // Check that if first returns false, second is not touched
CheckedTestingGenericMatcher first, second; CheckedTestingGenericMatcher first, second;
SECTION( "MatchAllOf" ) { SECTION( "MatchAllOf" ) {
@ -703,18 +745,17 @@ namespace { namespace MatchersTests {
} }
} }
template <typename Range> template <typename Range>
struct EqualsRangeMatcher : Catch::Matchers::MatcherGenericBase { struct EqualsRangeMatcher : Catch::Matchers::MatcherGenericBase {
EqualsRangeMatcher( Range const& range ): m_range{ range } {} EqualsRangeMatcher( Range const& range ): m_range{ range } {}
template<typename OtherRange> template <typename OtherRange> bool match( OtherRange const& other ) const {
bool match(OtherRange const& other) const {
using std::begin; using std::begin;
using std::end; using std::end;
return std::equal(begin(m_range), end(m_range), begin(other), end(other)); return std::equal(
begin( m_range ), end( m_range ), begin( other ), end( other ) );
} }
std::string describe() const override { std::string describe() const override {
@ -737,51 +778,70 @@ namespace { namespace MatchersTests {
std::vector<int> b{ 0, 1, 2 }; std::vector<int> b{ 0, 1, 2 };
std::list<int> c{ 4, 5, 6 }; std::list<int> c{ 4, 5, 6 };
REQUIRE_THAT(container, EqualsRange(a) || EqualsRange(b) || EqualsRange(c)); REQUIRE_THAT( container,
EqualsRange( a ) || EqualsRange( b ) || EqualsRange( c ) );
} }
TEST_CASE("Combining templated and concrete matchers", "[matchers][templated]") { TEST_CASE( "Combining templated and concrete matchers",
"[matchers][templated]" ) {
std::vector<int> vec{ 1, 3, 5 }; std::vector<int> vec{ 1, 3, 5 };
std::array<int, 3> a{ { 5, 3, 1 } }; std::array<int, 3> a{ { 5, 3, 1 } };
REQUIRE_THAT( vec, REQUIRE_THAT( vec,
Predicate<std::vector<int>>([](auto const& v) { Predicate<std::vector<int>>(
return std::all_of(v.begin(), v.end(), [](int elem) { []( auto const& v ) {
return std::all_of(
v.begin(), v.end(), []( int elem ) {
return elem % 2 == 1; return elem % 2 == 1;
} ); } );
}, "All elements are odd") && },
"All elements are odd" ) &&
!EqualsRange( a ) ); !EqualsRange( a ) );
const std::string str = "foobar"; const std::string str = "foobar";
const std::array<char, 6> arr{ { 'f', 'o', 'o', 'b', 'a', 'r' } }; const std::array<char, 6> arr{ { 'f', 'o', 'o', 'b', 'a', 'r' } };
const std::array<char, 6> bad_arr{ { 'o', 'o', 'f', 'b', 'a', 'r' } }; const std::array<char, 6> bad_arr{ { 'o', 'o', 'f', 'b', 'a', 'r' } };
using Catch::Matchers::StartsWith;
using Catch::Matchers::EndsWith; using Catch::Matchers::EndsWith;
using Catch::Matchers::StartsWith;
REQUIRE_THAT(str, StartsWith("foo") && EqualsRange(arr) && EndsWith("bar")); REQUIRE_THAT(
REQUIRE_THAT(str, StartsWith("foo") && !EqualsRange(bad_arr) && EndsWith("bar")); str, StartsWith( "foo" ) && EqualsRange( arr ) && EndsWith( "bar" ) );
REQUIRE_THAT( str,
StartsWith( "foo" ) && !EqualsRange( bad_arr ) &&
EndsWith( "bar" ) );
REQUIRE_THAT(str, EqualsRange(arr) && StartsWith("foo") && EndsWith("bar")); REQUIRE_THAT(
REQUIRE_THAT(str, !EqualsRange(bad_arr) && StartsWith("foo") && EndsWith("bar")); str, EqualsRange( arr ) && StartsWith( "foo" ) && EndsWith( "bar" ) );
REQUIRE_THAT( str,
!EqualsRange( bad_arr ) && StartsWith( "foo" ) &&
EndsWith( "bar" ) );
REQUIRE_THAT(str, EqualsRange(bad_arr) || (StartsWith("foo") && EndsWith("bar"))); REQUIRE_THAT( str,
REQUIRE_THAT(str, (StartsWith("foo") && EndsWith("bar")) || EqualsRange(bad_arr)); EqualsRange( bad_arr ) ||
( StartsWith( "foo" ) && EndsWith( "bar" ) ) );
REQUIRE_THAT( str,
( StartsWith( "foo" ) && EndsWith( "bar" ) ) ||
EqualsRange( bad_arr ) );
} }
TEST_CASE("Combining concrete matchers does not use templated matchers", "[matchers][templated]") { TEST_CASE( "Combining concrete matchers does not use templated matchers",
using Catch::Matchers::StartsWith; "[matchers][templated]" ) {
using Catch::Matchers::EndsWith; using Catch::Matchers::EndsWith;
using Catch::Matchers::StartsWith;
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith("bar") && !EndsWith("foo"))), std::is_same<decltype( StartsWith( "foo" ) ||
Catch::Matchers::Detail::MatchAnyOf<std::string> ( StartsWith( "bar" ) && EndsWith( "bar" ) &&
>::value); !EndsWith( "foo" ) ) ),
Catch::Matchers::Detail::MatchAnyOf<std::string>>::value );
} }
struct MatcherA : Catch::Matchers::MatcherGenericBase { struct MatcherA : Catch::Matchers::MatcherGenericBase {
std::string describe() const override { return "equals: (int) 1 or (float) 1.0f"; } std::string describe() const override {
return "equals: (int) 1 or (float) 1.0f";
}
bool match( int i ) const { return i == 1; } bool match( int i ) const { return i == 1; }
bool match( float f ) const { return f == 1.0f; } bool match( float f ) const { return f == 1.0f; }
}; };
@ -793,8 +853,7 @@ namespace { namespace MatchersTests {
struct MatcherC : Catch::Matchers::MatcherGenericBase { struct MatcherC : Catch::Matchers::MatcherGenericBase {
std::string describe() const override { return "equals: (T) 1"; } std::string describe() const override { return "equals: (T) 1"; }
template<typename T> template <typename T> bool match( T t ) const { return t == T{ 1 }; }
bool match(T t) const { return t == T{1}; }
}; };
struct MatcherD : Catch::Matchers::MatcherGenericBase { struct MatcherD : Catch::Matchers::MatcherGenericBase {
@ -803,108 +862,119 @@ namespace { namespace MatchersTests {
}; };
TEST_CASE( "Combining only templated matchers", "[matchers][templated]" ) { TEST_CASE( "Combining only templated matchers", "[matchers][templated]" ) {
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
decltype(MatcherA() || MatcherB()), std::is_same<decltype( MatcherA() || MatcherB() ),
Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB> Catch::Matchers::Detail::
>::value); MatchAnyOfGeneric<MatcherA, MatcherB>>::value );
REQUIRE_THAT( 1, MatcherA() || MatcherB() ); REQUIRE_THAT( 1, MatcherA() || MatcherB() );
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
decltype(MatcherA() && MatcherB()), std::is_same<decltype( MatcherA() && MatcherB() ),
Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB> Catch::Matchers::Detail::
>::value); MatchAllOfGeneric<MatcherA, MatcherB>>::value );
REQUIRE_THAT( 1, MatcherA() && MatcherB() ); REQUIRE_THAT( 1, MatcherA() && MatcherB() );
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
std::is_same<
decltype( MatcherA() || !MatcherB() ), decltype( MatcherA() || !MatcherB() ),
Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, Catch::Matchers::Detail::MatchNotOfGeneric<MatcherB>> Catch::Matchers::Detail::MatchAnyOfGeneric<
>::value); MatcherA,
Catch::Matchers::Detail::MatchNotOfGeneric<MatcherB>>>::value );
REQUIRE_THAT( 1, MatcherA() || !MatcherB() ); REQUIRE_THAT( 1, MatcherA() || !MatcherB() );
} }
TEST_CASE("Combining MatchAnyOfGeneric does not nest", "[matchers][templated]") { TEST_CASE( "Combining MatchAnyOfGeneric does not nest",
"[matchers][templated]" ) {
// MatchAnyOfGeneric LHS + some matcher RHS // MatchAnyOfGeneric LHS + some matcher RHS
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
std::is_same<
decltype( ( MatcherA() || MatcherB() ) || MatcherC() ), decltype( ( MatcherA() || MatcherB() ) || MatcherC() ),
Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> Catch::Matchers::Detail::
>::value); MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC>>::value );
REQUIRE_THAT( 1, ( MatcherA() || MatcherB() ) || MatcherC() ); REQUIRE_THAT( 1, ( MatcherA() || MatcherB() ) || MatcherC() );
// some matcher LHS + MatchAnyOfGeneric RHS // some matcher LHS + MatchAnyOfGeneric RHS
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
std::is_same<
decltype( MatcherA() || ( MatcherB() || MatcherC() ) ), decltype( MatcherA() || ( MatcherB() || MatcherC() ) ),
Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> Catch::Matchers::Detail::
>::value); MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC>>::value );
REQUIRE_THAT( 1, MatcherA() || ( MatcherB() || MatcherC() ) ); REQUIRE_THAT( 1, MatcherA() || ( MatcherB() || MatcherC() ) );
// MatchAnyOfGeneric LHS + MatchAnyOfGeneric RHS // MatchAnyOfGeneric LHS + MatchAnyOfGeneric RHS
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
decltype((MatcherA() || MatcherB()) || (MatcherC() || MatcherD())), std::is_same<
Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> decltype( ( MatcherA() || MatcherB() ) ||
>::value); ( MatcherC() || MatcherD() ) ),
Catch::Matchers::Detail::
MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD>>::
value );
REQUIRE_THAT(1, (MatcherA() || MatcherB()) || (MatcherC() || MatcherD())); REQUIRE_THAT(
1, ( MatcherA() || MatcherB() ) || ( MatcherC() || MatcherD() ) );
} }
TEST_CASE("Combining MatchAllOfGeneric does not nest", "[matchers][templated]") { TEST_CASE( "Combining MatchAllOfGeneric does not nest",
"[matchers][templated]" ) {
// MatchAllOfGeneric lhs + some matcher RHS // MatchAllOfGeneric lhs + some matcher RHS
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
std::is_same<
decltype( ( MatcherA() && MatcherB() ) && MatcherC() ), decltype( ( MatcherA() && MatcherB() ) && MatcherC() ),
Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> Catch::Matchers::Detail::
>::value); MatchAllOfGeneric<MatcherA, MatcherB, MatcherC>>::value );
REQUIRE_THAT( 1, ( MatcherA() && MatcherB() ) && MatcherC() ); REQUIRE_THAT( 1, ( MatcherA() && MatcherB() ) && MatcherC() );
// some matcher LHS + MatchAllOfGeneric RSH // some matcher LHS + MatchAllOfGeneric RSH
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
std::is_same<
decltype( MatcherA() && ( MatcherB() && MatcherC() ) ), decltype( MatcherA() && ( MatcherB() && MatcherC() ) ),
Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> Catch::Matchers::Detail::
>::value); MatchAllOfGeneric<MatcherA, MatcherB, MatcherC>>::value );
REQUIRE_THAT( 1, MatcherA() && ( MatcherB() && MatcherC() ) ); REQUIRE_THAT( 1, MatcherA() && ( MatcherB() && MatcherC() ) );
// MatchAllOfGeneric LHS + MatchAllOfGeneric RHS // MatchAllOfGeneric LHS + MatchAllOfGeneric RHS
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
decltype((MatcherA() && MatcherB()) && (MatcherC() && MatcherD())), std::is_same<
Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> decltype( ( MatcherA() && MatcherB() ) &&
>::value); ( MatcherC() && MatcherD() ) ),
Catch::Matchers::Detail::
MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD>>::
value );
REQUIRE_THAT(1, (MatcherA() && MatcherB()) && (MatcherC() && MatcherD())); REQUIRE_THAT(
1, ( MatcherA() && MatcherB() ) && ( MatcherC() && MatcherD() ) );
} }
TEST_CASE("Combining MatchNotOfGeneric does not nest", "[matchers][templated]") { TEST_CASE( "Combining MatchNotOfGeneric does not nest",
STATIC_REQUIRE(std::is_same< "[matchers][templated]" ) {
STATIC_REQUIRE(
std::is_same<
decltype( !MatcherA() ), decltype( !MatcherA() ),
Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA> Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA>>::value );
>::value);
REQUIRE_THAT( 0, !MatcherA() ); REQUIRE_THAT( 0, !MatcherA() );
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
decltype(!!MatcherA()), std::is_same<decltype( !!MatcherA() ), MatcherA const&>::value );
MatcherA const&
>::value);
REQUIRE_THAT( 1, !!MatcherA() ); REQUIRE_THAT( 1, !!MatcherA() );
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
std::is_same<
decltype( !!!MatcherA() ), decltype( !!!MatcherA() ),
Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA> Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA>>::value );
>::value);
REQUIRE_THAT( 0, !!!MatcherA() ); REQUIRE_THAT( 0, !!!MatcherA() );
STATIC_REQUIRE(std::is_same< STATIC_REQUIRE(
decltype(!!!!MatcherA()), std::is_same<decltype( !!!!MatcherA() ), MatcherA const&>::value );
MatcherA const &
>::value);
REQUIRE_THAT( 1, !!!!MatcherA() ); REQUIRE_THAT( 1, !!!!MatcherA() );
} }
@ -912,7 +982,8 @@ namespace { namespace MatchersTests {
struct EvilAddressOfOperatorUsed : std::exception { struct EvilAddressOfOperatorUsed : std::exception {
EvilAddressOfOperatorUsed() {} EvilAddressOfOperatorUsed() {}
const char* what() const noexcept override { const char* what() const noexcept override {
return "overloaded address-of operator of matcher was used instead of std::addressof"; return "overloaded address-of operator of matcher was used instead of "
"std::addressof";
} }
}; };
@ -924,25 +995,19 @@ namespace { namespace MatchersTests {
}; };
struct EvilMatcher : Catch::Matchers::MatcherGenericBase { struct EvilMatcher : Catch::Matchers::MatcherGenericBase {
std::string describe() const override { std::string describe() const override { return "equals: 45"; }
return "equals: 45";
}
bool match(int i) const { bool match( int i ) const { return i == 45; }
return i == 45;
}
EvilMatcher const* operator& () const { EvilMatcher const* operator&() const { throw EvilAddressOfOperatorUsed(); }
throw EvilAddressOfOperatorUsed();
}
int operator,(EvilMatcher const&) const { int operator,( EvilMatcher const& ) const { throw EvilCommaOperatorUsed(); }
throw EvilCommaOperatorUsed();
}
}; };
TEST_CASE("Overloaded comma or address-of operators are not used", "[matchers][templated]") { TEST_CASE( "Overloaded comma or address-of operators are not used",
REQUIRE_THROWS_AS((EvilMatcher(), EvilMatcher()), EvilCommaOperatorUsed); "[matchers][templated]" ) {
REQUIRE_THROWS_AS( ( EvilMatcher(), EvilMatcher() ),
EvilCommaOperatorUsed );
REQUIRE_THROWS_AS( &EvilMatcher(), EvilAddressOfOperatorUsed ); REQUIRE_THROWS_AS( &EvilMatcher(), EvilAddressOfOperatorUsed );
REQUIRE_NOTHROW( EvilMatcher() || ( EvilMatcher() && !EvilMatcher() ) ); REQUIRE_NOTHROW( EvilMatcher() || ( EvilMatcher() && !EvilMatcher() ) );
REQUIRE_NOTHROW( ( EvilMatcher() && EvilMatcher() ) || !EvilMatcher() ); REQUIRE_NOTHROW( ( EvilMatcher() && EvilMatcher() ) || !EvilMatcher() );
@ -955,14 +1020,9 @@ namespace { namespace MatchersTests {
ImmovableMatcher& operator=( ImmovableMatcher const& ) = delete; ImmovableMatcher& operator=( ImmovableMatcher const& ) = delete;
ImmovableMatcher& operator=( ImmovableMatcher&& ) = delete; ImmovableMatcher& operator=( ImmovableMatcher&& ) = delete;
std::string describe() const override { std::string describe() const override { return "always false"; }
return "always false";
}
template<typename T> template <typename T> bool match( T&& ) const { return false; }
bool match(T&&) const {
return false;
}
}; };
struct MatcherWasMovedOrCopied : std::exception { struct MatcherWasMovedOrCopied : std::exception {
@ -974,12 +1034,12 @@ namespace { namespace MatchersTests {
struct ThrowOnCopyOrMoveMatcher : Catch::Matchers::MatcherGenericBase { struct ThrowOnCopyOrMoveMatcher : Catch::Matchers::MatcherGenericBase {
ThrowOnCopyOrMoveMatcher() = default; ThrowOnCopyOrMoveMatcher() = default;
[[noreturn]] [[noreturn]] ThrowOnCopyOrMoveMatcher( ThrowOnCopyOrMoveMatcher const& ):
ThrowOnCopyOrMoveMatcher(ThrowOnCopyOrMoveMatcher const&): Catch::Matchers::MatcherGenericBase() { Catch::Matchers::MatcherGenericBase() {
throw MatcherWasMovedOrCopied(); throw MatcherWasMovedOrCopied();
} }
[[noreturn]] [[noreturn]] ThrowOnCopyOrMoveMatcher( ThrowOnCopyOrMoveMatcher&& ):
ThrowOnCopyOrMoveMatcher(ThrowOnCopyOrMoveMatcher &&): Catch::Matchers::MatcherGenericBase() { Catch::Matchers::MatcherGenericBase() {
throw MatcherWasMovedOrCopied(); throw MatcherWasMovedOrCopied();
} }
ThrowOnCopyOrMoveMatcher& operator=( ThrowOnCopyOrMoveMatcher const& ) { ThrowOnCopyOrMoveMatcher& operator=( ThrowOnCopyOrMoveMatcher const& ) {
@ -989,39 +1049,35 @@ namespace { namespace MatchersTests {
throw MatcherWasMovedOrCopied(); throw MatcherWasMovedOrCopied();
} }
std::string describe() const override { std::string describe() const override { return "always false"; }
return "always false";
}
template<typename T> template <typename T> bool match( T&& ) const { return false; }
bool match(T&&) const {
return false;
}
}; };
TEST_CASE("Matchers are not moved or copied", "[matchers][templated][approvals]") { TEST_CASE( "Matchers are not moved or copied",
REQUIRE_NOTHROW((ThrowOnCopyOrMoveMatcher() && ThrowOnCopyOrMoveMatcher()) || !ThrowOnCopyOrMoveMatcher()); "[matchers][templated][approvals]" ) {
REQUIRE_NOTHROW(
( ThrowOnCopyOrMoveMatcher() && ThrowOnCopyOrMoveMatcher() ) ||
!ThrowOnCopyOrMoveMatcher() );
} }
TEST_CASE("Immovable matchers can be used", "[matchers][templated][approvals]") { TEST_CASE( "Immovable matchers can be used",
REQUIRE_THAT(123, (ImmovableMatcher() && ImmovableMatcher()) || !ImmovableMatcher()); "[matchers][templated][approvals]" ) {
REQUIRE_THAT( 123,
( ImmovableMatcher() && ImmovableMatcher() ) ||
!ImmovableMatcher() );
} }
struct ReferencingMatcher : Catch::Matchers::MatcherGenericBase { struct ReferencingMatcher : Catch::Matchers::MatcherGenericBase {
std::string describe() const override { std::string describe() const override { return "takes reference"; }
return "takes reference"; bool match( int& i ) const { return i == 22; }
}
bool match(int& i) const {
return i == 22;
}
}; };
TEST_CASE("Matchers can take references", "[matchers][templated][approvals]") { TEST_CASE( "Matchers can take references",
"[matchers][templated][approvals]" ) {
REQUIRE_THAT( 22, ReferencingMatcher{} ); REQUIRE_THAT( 22, ReferencingMatcher{} );
} }
} } // namespace MatchersTests
#ifdef __clang__ #ifdef __clang__
# pragma clang diagnostic pop # pragma clang diagnostic pop
#endif #endif

View File

@ -19,28 +19,25 @@
#include <array> #include <array>
#include <tuple> #include <tuple>
namespace { namespace MiscTests { namespace {
#ifndef MISC_TEST_HELPERS_INCLUDED // Don't compile this more than once per TU static const char* makeString(bool makeNull) {
#define MISC_TEST_HELPERS_INCLUDED
inline const char* makeString( bool makeNull ) {
return makeNull ? nullptr : "valid string"; return makeNull ? nullptr : "valid string";
} }
inline bool testCheckedIf( bool flag ) { static bool testCheckedIf(bool flag) {
CHECKED_IF(flag) CHECKED_IF(flag)
return true; return true;
else else
return false; return false;
} }
inline bool testCheckedElse( bool flag ) { static bool testCheckedElse(bool flag) {
CHECKED_ELSE(flag) CHECKED_ELSE(flag)
return false; return false;
return true; return true;
} }
inline unsigned int Factorial( unsigned int number ) { static unsigned int Factorial(unsigned int number) {
return number > 1 ? Factorial(number - 1) * number : 1; return number > 1 ? Factorial(number - 1) * number : 1;
} }
@ -48,7 +45,7 @@ static int f() {
return 1; return 1;
} }
inline void manuallyRegisteredTestFunction() { static void manuallyRegisteredTestFunction() {
SUCCEED("was called"); SUCCEED("was called");
} }
@ -72,7 +69,8 @@ template<typename T, size_t S>
struct Bar { struct Bar {
size_t size() { return S; } size_t size() { return S; }
}; };
#endif
}
TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) { TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) {
int a = 1; int a = 1;
@ -521,5 +519,3 @@ TEMPLATE_TEST_CASE_SIG("#1954 - 7 arg template test case sig compiles", "[regres
(1, 1, 1, 1, 1, 0, 0), (5, 1, 1, 1, 1, 0, 0), (5, 3, 1, 1, 1, 0, 0)) { (1, 1, 1, 1, 1, 0, 0), (5, 1, 1, 1, 1, 0, 0), (5, 3, 1, 1, 1, 0, 0)) {
SUCCEED(); SUCCEED();
} }
}} // namespace MiscTests