Skip to content

Commit

Permalink
feat: matches::range::any_element
Browse files Browse the repository at this point in the history
  • Loading branch information
DNKpp committed Oct 25, 2024
1 parent be32abe commit ccfff4a
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 1 deletion.
31 changes: 30 additions & 1 deletion include/mimic++/Matcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ namespace mimicpp::matches::range
}

/**
* \brief Tests, whether the each element of the target range matches the specified matcher.
* \brief Tests, whether each element of the target range matches the specified matcher.
* \param matcher The matcher.
*/
template <typename Matcher>
Expand Down Expand Up @@ -960,6 +960,35 @@ namespace mimicpp::matches::range
};
}

/**
* \brief Tests, whether any element of the target range matches the specified matcher.
* \param matcher The matcher.
*/
template <typename Matcher>
[[nodiscard]]
constexpr auto any_element(Matcher&& matcher)
{
using MatcherT = std::remove_cvref_t<Matcher>;
return PredicateMatcher{
[](std::ranges::range auto&& target, const MatcherT& m)
{
return std::ranges::any_of(
target,
[&](const auto& element) { return m.matches(element); });
},
"any el in range: el {}",
"none el in range: el {}",
std::tuple{
mimicpp::detail::arg_storage<
MatcherT,
std::identity,
decltype([](const auto& m) { return mimicpp::detail::describe_hook::describe(m); })>{
std::forward<MatcherT>(matcher)
}
}
};
}

/**
* \}
*/
Expand Down
62 changes: 62 additions & 0 deletions test/unit-tests/matchers/RangeMatchers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,3 +484,65 @@ TEST_CASE(
}
}
}

TEST_CASE(
"matches::range::any_element matches when at least one elements of the target range matches.",
"[matcher][matcher::range]"
)
{
SECTION("Plain matcher.")
{
SECTION("When any element matches the matcher, it's a match.")
{
const auto threshold = GENERATE(42, 1337);
const auto matcher = matches::range::any_element(matches::ge(threshold));

const std::vector target{42, 1337};
REQUIRE(matcher.matches(target));
REQUIRE_THAT(
matcher.describe(),
Catch::Matchers::StartsWith("any el in range: el >= "));
}

SECTION("When no element matches the matcher, it's no match.")
{
const std::vector target = GENERATE(
std::vector<int>{},
(std::vector{42, 1337}));
const auto matcher = matches::range::any_element(matches::gt(1337));

REQUIRE(!matcher.matches(target));
REQUIRE_THAT(
matcher.describe(),
Catch::Matchers::Equals("any el in range: el > 1337"));
}
}

SECTION("Matcher can be inverted.")
{
SECTION("When any element matches the matcher, it's no match.")
{
const auto threshold = GENERATE(42, 1337);
const auto matcher = !matches::range::any_element(matches::ge(threshold));

const std::vector target{42, 1337};
REQUIRE(!matcher.matches(target));
REQUIRE_THAT(
matcher.describe(),
Catch::Matchers::StartsWith("none el in range: el >= "));
}

SECTION("When no element matches the matcher, it's a match.")
{
const std::vector target = GENERATE(
std::vector<int>{},
(std::vector{42, 1337}));
const auto matcher = !matches::range::any_element(matches::gt(1337));

REQUIRE(matcher.matches(target));
REQUIRE_THAT(
matcher.describe(),
Catch::Matchers::StartsWith("none el in range: el > 1337"));
}
}
}

0 comments on commit ccfff4a

Please sign in to comment.