mirror of
https://github.com/catchorg/Catch2.git
synced 2025-08-02 05:15:39 +02:00
Add AllTrue, AnyTrue, NoneTrue matchers
This commit is contained in:

committed by
Martin Hořeňovský

parent
f993b702c6
commit
1bd233866c
@@ -547,31 +547,288 @@ TEST_CASE("Usage of NoneMatch range matcher", "[matchers][templated][quantifiers
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct ConvertibleToBool
|
||||
{
|
||||
bool v;
|
||||
|
||||
// This is a C++17 extension, and GCC refuses to compile such code
|
||||
// unless it is set to C++17 or later
|
||||
explicit operator bool() const
|
||||
{
|
||||
return v;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace Catch {
|
||||
template <>
|
||||
struct StringMaker<ConvertibleToBool> {
|
||||
static std::string
|
||||
convert( ConvertibleToBool const& convertible_to_bool ) {
|
||||
return ::Catch::Detail::stringify( convertible_to_bool.v );
|
||||
}
|
||||
};
|
||||
} // namespace Catch
|
||||
|
||||
TEST_CASE("Usage of AllTrue range matcher", "[matchers][templated][quantifiers]") {
|
||||
using Catch::Matchers::AllTrue;
|
||||
|
||||
SECTION( "Basic usage" ) {
|
||||
SECTION( "All true evaluates to true" ) {
|
||||
std::array<bool, 5> const data{ { true, true, true, true, true } };
|
||||
REQUIRE_THAT( data, AllTrue() );
|
||||
}
|
||||
SECTION( "Empty evaluates to true" ) {
|
||||
std::array<bool, 0> const data{};
|
||||
REQUIRE_THAT( data, AllTrue() );
|
||||
}
|
||||
SECTION( "One false evalutes to false" ) {
|
||||
std::array<bool, 5> const data{ { true, true, false, true, true } };
|
||||
REQUIRE_THAT( data, !AllTrue() );
|
||||
}
|
||||
SECTION( "All false evaluates to false" ) {
|
||||
std::array<bool, 5> const data{
|
||||
{ false, false, false, false, false } };
|
||||
REQUIRE_THAT( data, !AllTrue() );
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "Contained type is convertible to bool" ) {
|
||||
SECTION( "All true evaluates to true" ) {
|
||||
std::array<ConvertibleToBool, 5> const data{
|
||||
{ { true }, { true }, { true }, { true }, { true } } };
|
||||
REQUIRE_THAT( data, AllTrue() );
|
||||
}
|
||||
SECTION( "One false evalutes to false" ) {
|
||||
std::array<ConvertibleToBool, 5> const data{
|
||||
{ { true }, { true }, { false }, { true }, { true } } };
|
||||
REQUIRE_THAT( data, !AllTrue() );
|
||||
}
|
||||
SECTION( "All false evaluates to false" ) {
|
||||
std::array<ConvertibleToBool, 5> const data{
|
||||
{ { false }, { false }, { false }, { false }, { false } } };
|
||||
REQUIRE_THAT( data, !AllTrue() );
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "Shortcircuiting" ) {
|
||||
SECTION( "All are read" ) {
|
||||
with_mocked_iterator_access<bool> const mocked{
|
||||
true, true, true, true, true };
|
||||
REQUIRE_THAT( mocked, AllTrue() );
|
||||
REQUIRE( mocked.m_derefed[0] );
|
||||
REQUIRE( mocked.m_derefed[1] );
|
||||
REQUIRE( mocked.m_derefed[2] );
|
||||
REQUIRE( mocked.m_derefed[3] );
|
||||
REQUIRE( mocked.m_derefed[4] );
|
||||
}
|
||||
SECTION( "Short-circuited" ) {
|
||||
with_mocked_iterator_access<bool> const mocked{
|
||||
true, true, false, true, true };
|
||||
REQUIRE_THAT( mocked, !AllTrue() );
|
||||
REQUIRE( mocked.m_derefed[0] );
|
||||
REQUIRE( mocked.m_derefed[1] );
|
||||
REQUIRE( mocked.m_derefed[2] );
|
||||
REQUIRE_FALSE( mocked.m_derefed[3] );
|
||||
REQUIRE_FALSE( mocked.m_derefed[4] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Usage of NoneTrue range matcher", "[matchers][templated][quantifiers]" ) {
|
||||
using Catch::Matchers::NoneTrue;
|
||||
|
||||
SECTION( "Basic usage" ) {
|
||||
SECTION( "All true evaluates to false" ) {
|
||||
std::array<bool, 5> const data{ { true, true, true, true, true } };
|
||||
REQUIRE_THAT( data, !NoneTrue() );
|
||||
}
|
||||
SECTION( "Empty evaluates to true" ) {
|
||||
std::array<bool, 0> const data{};
|
||||
REQUIRE_THAT( data, NoneTrue() );
|
||||
}
|
||||
SECTION( "One true evalutes to false" ) {
|
||||
std::array<bool, 5> const data{
|
||||
{ false, false, true, false, false } };
|
||||
REQUIRE_THAT( data, !NoneTrue() );
|
||||
}
|
||||
SECTION( "All false evaluates to true" ) {
|
||||
std::array<bool, 5> const data{
|
||||
{ false, false, false, false, false } };
|
||||
REQUIRE_THAT( data, NoneTrue() );
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "Contained type is convertible to bool" ) {
|
||||
SECTION( "All true evaluates to false" ) {
|
||||
std::array<ConvertibleToBool, 5> const data{
|
||||
{ { true }, { true }, { true }, { true }, { true } } };
|
||||
REQUIRE_THAT( data, !NoneTrue() );
|
||||
}
|
||||
SECTION( "One true evalutes to false" ) {
|
||||
std::array<ConvertibleToBool, 5> const data{
|
||||
{ { false }, { false }, { true }, { false }, { false } } };
|
||||
REQUIRE_THAT( data, !NoneTrue() );
|
||||
}
|
||||
SECTION( "All false evaluates to true" ) {
|
||||
std::array<ConvertibleToBool, 5> const data{
|
||||
{ { false }, { false }, { false }, { false }, { false } } };
|
||||
REQUIRE_THAT( data, NoneTrue() );
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "Shortcircuiting" ) {
|
||||
SECTION( "All are read" ) {
|
||||
with_mocked_iterator_access<bool> const mocked{
|
||||
false, false, false, false, false };
|
||||
REQUIRE_THAT( mocked, NoneTrue() );
|
||||
REQUIRE( mocked.m_derefed[0] );
|
||||
REQUIRE( mocked.m_derefed[1] );
|
||||
REQUIRE( mocked.m_derefed[2] );
|
||||
REQUIRE( mocked.m_derefed[3] );
|
||||
REQUIRE( mocked.m_derefed[4] );
|
||||
}
|
||||
SECTION( "Short-circuited" ) {
|
||||
with_mocked_iterator_access<bool> const mocked{
|
||||
false, false, true, true, true };
|
||||
REQUIRE_THAT( mocked, !NoneTrue() );
|
||||
REQUIRE( mocked.m_derefed[0] );
|
||||
REQUIRE( mocked.m_derefed[1] );
|
||||
REQUIRE( mocked.m_derefed[2] );
|
||||
REQUIRE_FALSE( mocked.m_derefed[3] );
|
||||
REQUIRE_FALSE( mocked.m_derefed[4] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE( "Usage of AnyTrue range matcher", "[matchers][templated][quantifiers]" ) {
|
||||
using Catch::Matchers::AnyTrue;
|
||||
|
||||
SECTION( "Basic usage" ) {
|
||||
SECTION( "All true evaluates to true" ) {
|
||||
std::array<bool, 5> const data{ { true, true, true, true, true } };
|
||||
REQUIRE_THAT( data, AnyTrue() );
|
||||
}
|
||||
SECTION( "Empty evaluates to false" ) {
|
||||
std::array<bool, 0> const data{};
|
||||
REQUIRE_THAT( data, !AnyTrue() );
|
||||
}
|
||||
SECTION( "One true evalutes to true" ) {
|
||||
std::array<bool, 5> const data{
|
||||
{ false, false, true, false, false } };
|
||||
REQUIRE_THAT( data, AnyTrue() );
|
||||
}
|
||||
SECTION( "All false evaluates to false" ) {
|
||||
std::array<bool, 5> const data{
|
||||
{ false, false, false, false, false } };
|
||||
REQUIRE_THAT( data, !AnyTrue() );
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "Contained type is convertible to bool" ) {
|
||||
SECTION( "All true evaluates to true" ) {
|
||||
std::array<ConvertibleToBool, 5> const data{
|
||||
{ { true }, { true }, { true }, { true }, { true } } };
|
||||
REQUIRE_THAT( data, AnyTrue() );
|
||||
}
|
||||
SECTION( "One true evalutes to true" ) {
|
||||
std::array<ConvertibleToBool, 5> const data{
|
||||
{ { false }, { false }, { true }, { false }, { false } } };
|
||||
REQUIRE_THAT( data, AnyTrue() );
|
||||
}
|
||||
SECTION( "All false evaluates to false" ) {
|
||||
std::array<ConvertibleToBool, 5> const data{
|
||||
{ { false }, { false }, { false }, { false }, { false } } };
|
||||
REQUIRE_THAT( data, !AnyTrue() );
|
||||
}
|
||||
}
|
||||
|
||||
SECTION( "Shortcircuiting" ) {
|
||||
SECTION( "All are read" ) {
|
||||
with_mocked_iterator_access<bool> const mocked{
|
||||
false, false, false, false, true };
|
||||
REQUIRE_THAT( mocked, AnyTrue() );
|
||||
REQUIRE( mocked.m_derefed[0] );
|
||||
REQUIRE( mocked.m_derefed[1] );
|
||||
REQUIRE( mocked.m_derefed[2] );
|
||||
REQUIRE( mocked.m_derefed[3] );
|
||||
REQUIRE( mocked.m_derefed[4] );
|
||||
}
|
||||
SECTION( "Short-circuited" ) {
|
||||
with_mocked_iterator_access<bool> const mocked{
|
||||
false, false, true, true, true };
|
||||
REQUIRE_THAT( mocked, AnyTrue() );
|
||||
REQUIRE( mocked.m_derefed[0] );
|
||||
REQUIRE( mocked.m_derefed[1] );
|
||||
REQUIRE( mocked.m_derefed[2] );
|
||||
REQUIRE_FALSE( mocked.m_derefed[3] );
|
||||
REQUIRE_FALSE( mocked.m_derefed[4] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("All/Any/None True matchers support types with ADL begin",
|
||||
"[approvals][matchers][quantifiers][templated]") {
|
||||
using Catch::Matchers::AllTrue;
|
||||
using Catch::Matchers::NoneTrue;
|
||||
using Catch::Matchers::AnyTrue;
|
||||
|
||||
|
||||
SECTION( "Type requires ADL found begin and end" ) {
|
||||
unrelated::needs_ADL_begin<bool> const needs_adl{
|
||||
true, true, true, true, true };
|
||||
REQUIRE_THAT( needs_adl, AllTrue() );
|
||||
}
|
||||
|
||||
SECTION( "Type requires ADL found begin and end" ) {
|
||||
unrelated::needs_ADL_begin<bool> const needs_adl{
|
||||
false, false, false, false, false };
|
||||
REQUIRE_THAT( needs_adl, NoneTrue() );
|
||||
}
|
||||
|
||||
SECTION( "Type requires ADL found begin and end" ) {
|
||||
unrelated::needs_ADL_begin<bool> const needs_adl{
|
||||
false, false, true, false, false };
|
||||
REQUIRE_THAT( needs_adl, AnyTrue() );
|
||||
}
|
||||
}
|
||||
|
||||
// Range loop iterating over range with different types for begin and end is a
|
||||
// C++17 feature, and GCC refuses to compile such code unless the lang mode is
|
||||
// set to C++17 or later.
|
||||
#if defined(CATCH_CPP17_OR_GREATER)
|
||||
|
||||
TEST_CASE( "The quantifier range matchers support types with different types returned from begin and end",
|
||||
"[matchers][templated][quantifiers][approvals]" ) {
|
||||
using Catch::Matchers::AllMatch;
|
||||
using Catch::Matchers::AllTrue;
|
||||
using Catch::Matchers::AnyMatch;
|
||||
using Catch::Matchers::AnyTrue;
|
||||
using Catch::Matchers::NoneMatch;
|
||||
using Catch::Matchers::NoneTrue;
|
||||
|
||||
using Catch::Matchers::Predicate;
|
||||
|
||||
has_different_begin_end_types<int> diff_types{1, 2, 3, 4, 5};
|
||||
REQUIRE_THAT( diff_types, !AllMatch( Predicate<int>( []( int elem ) {
|
||||
return elem < 3;
|
||||
} ) ) );
|
||||
SECTION( "AllAnyNoneMatch" ) {
|
||||
has_different_begin_end_types<int> diff_types{ 1, 2, 3, 4, 5 };
|
||||
REQUIRE_THAT( diff_types, !AllMatch( Predicate<int>( []( int elem ) {
|
||||
return elem < 3;
|
||||
} ) ) );
|
||||
|
||||
REQUIRE_THAT( diff_types, AnyMatch( Predicate<int>( []( int elem ) {
|
||||
return elem < 2;
|
||||
} ) ) );
|
||||
REQUIRE_THAT( diff_types, AnyMatch( Predicate<int>( []( int elem ) {
|
||||
return elem < 2;
|
||||
} ) ) );
|
||||
|
||||
REQUIRE_THAT( diff_types, !NoneMatch( Predicate<int>( []( int elem ) {
|
||||
return elem < 3;
|
||||
} ) ) );
|
||||
REQUIRE_THAT( diff_types, !NoneMatch( Predicate<int>( []( int elem ) {
|
||||
return elem < 3;
|
||||
} ) ) );
|
||||
}
|
||||
SECTION( "AllAnyNoneTrue" ) {
|
||||
has_different_begin_end_types<bool> diff_types{ false, false, true, false, false };
|
||||
|
||||
REQUIRE_THAT( diff_types, !AllTrue() );
|
||||
REQUIRE_THAT( diff_types, AnyTrue() );
|
||||
REQUIRE_THAT( diff_types, !NoneTrue() );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user