Skip to content

Commit

Permalink
all_of/none_of/any_of sans docs
Browse files Browse the repository at this point in the history
  • Loading branch information
rollbear committed Sep 28, 2024
1 parent 7d6cda8 commit 7d3e5c6
Show file tree
Hide file tree
Showing 3 changed files with 354 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/trompeloeil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "trompeloeil/matcher/range.hpp"
#endif
#include "trompeloeil/matcher/re.hpp"
#include "trompeloeil/matcher/set_predicate.hpp"
#include "trompeloeil/sequence.hpp"
#include "trompeloeil/stream_tracer.hpp"
#ifdef __cpp_impl_coroutine
Expand Down
173 changes: 173 additions & 0 deletions include/trompeloeil/matcher/set_predicate.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/*
* Trompeloeil C++ mocking framework
*
* Copyright (C) Björn Fahller
*
* Use, modification and distribution is subject to the
* Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy atl
* http://www.boost.org/LICENSE_1_0.txt)
*
* Project home: https://github.com/rollbear/trompeloeil
*/

#ifndef TROMPELOEIL_SET_PREDICATE_HPP
#define TROMPELOEIL_SET_PREDICATE_HPP

#ifndef TROMPELOEIL_MATCHER_HPP
#include "../matcher.hpp"
#endif

namespace trompeloeil {
namespace impl {
struct any_of_checker
{
template <typename T, typename ... Cs>
bool operator()(const T& t, const Cs& ... compare) const
{
bool any_true = false;
trompeloeil::ignore(std::initializer_list<bool>{
(any_true = any_true || trompeloeil::param_matches(compare, std::ref(t)))...
});
return any_true;
}
};
struct any_of_printer
{
template <typename ... Cs>
void operator()(std::ostream& os, const Cs& ... compare) const
{
os << " to be any of {";
const char* sep = " ";
const auto print = [&](const auto& v) {
os << std::exchange(sep, ", ") << v;
return 0;
};
trompeloeil::ignore(std::initializer_list<int>{
(print(compare))...
});
os << " }";
}
};
}

template <
typename Type = trompeloeil::wildcard,
typename ... Cs,
typename R = make_matcher_return<
Type,
impl::any_of_checker,
impl::any_of_printer,
Cs...
>
>
R any_of(Cs&& ... cs)
{
return trompeloeil::make_matcher<Type>(
impl::any_of_checker{},
impl::any_of_printer{},
std::forward<Cs>(cs)...);
}

namespace impl {
struct none_of_checker
{
template <typename T, typename ... Cs>
bool operator()(const T& t, const Cs& ... compare) const
{
bool any_true = false;
trompeloeil::ignore(std::initializer_list<bool>{
(any_true = any_true || trompeloeil::param_matches(compare, std::ref(t)))...
});
return !any_true;
}
};
struct none_of_printer
{
template <typename ... Cs>
void operator()(std::ostream& os, const Cs& ... compare) const
{
os << " to be none of {";
const char* sep = " ";
const auto print = [&](const auto& v) {
os << std::exchange(sep, ", ") << v;
return 0;
};
trompeloeil::ignore(std::initializer_list<int>{
(print(compare))...
});
os << " }";
}
};
}

template <
typename Type = trompeloeil::wildcard,
typename ... Cs,
typename R = make_matcher_return<
Type,
impl::none_of_checker,
impl::none_of_printer,
Cs...
>
>
R none_of(Cs&& ... cs)
{
return trompeloeil::make_matcher<Type>(
impl::none_of_checker{},
impl::none_of_printer{},
std::forward<Cs>(cs)...);
}

namespace impl {
struct all_of_checker
{
template <typename T, typename ... Cs>
bool operator()(const T& t, const Cs& ... compare) const
{
bool all_true = true;
trompeloeil::ignore(std::initializer_list<bool>{
(all_true = all_true && trompeloeil::param_matches(compare, std::ref(t)))...
});
return all_true;
}
};
struct all_of_printer
{
template <typename ... Cs>
void operator()(std::ostream& os, const Cs& ... compare) const
{
os << " to be all of {";
const char* sep = " ";
const auto print = [&](const auto& v) {
os << std::exchange(sep, ", ") << v;
return 0;
};
trompeloeil::ignore(std::initializer_list<int>{
(print(compare))...
});
os << " }";
}
};
}

template <
typename Type = trompeloeil::wildcard,
typename ... Cs,
typename R = make_matcher_return<
Type,
impl::all_of_checker,
impl::all_of_printer,
Cs...
>
>
R all_of(Cs&& ... cs)
{
return trompeloeil::make_matcher<Type>(
impl::all_of_checker{},
impl::all_of_printer{},
std::forward<Cs>(cs)...);
}

}
#endif // TROMPELOEIL_SET_PREDICATE_HPP
180 changes: 180 additions & 0 deletions test/compiling_tests_14.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2375,6 +2375,186 @@ TEST_CASE_METHOD(
REQUIRE(reports.empty());
}

TEST_CASE_METHOD(
Fixture,
"C++14: any_of is true if at least one element matches",
"[C++14][matching][matchers][any_of]"
)
{
{
mock_str obj;
using trompeloeil::any_of;
using trompeloeil::eq;
REQUIRE_CALL(obj, str(any_of("", eq("foo"))));
obj.str("foo");
}
REQUIRE(reports.empty());
}

TEST_CASE_METHOD(
Fixture,
"C++14: any_of reports if none of the element matches",
"[C++14][matching][matchers][any_of]"
)
{
try {
mock_str obj;
using trompeloeil::any_of;
using trompeloeil::eq;
REQUIRE_CALL(obj, str(any_of("", eq("foo"))));
obj.str("bar");
FAIL("didn't throw");
}
catch (reported) {
REQUIRE(reports.size() == 1U);
auto re = R":(No match for call of str with signature void\(std::string\) with\.
param _1 == bar
Tried obj\.str\(any_of\(\"\", eq\(\"foo\"\)\)\) at [A-Za-z0-9_ ./:\]*:[0-9]*.*
Expected _1 to be any of \{ , == foo \}):";
INFO("report=" << reports.front().msg);
REQUIRE(std::regex_search(reports.front().msg, std::regex(re)));
}
}

TEST_CASE_METHOD(
Fixture,
"C++14: any_of can be disambiguated with explicit type",
"[C++14][matching][matchers][any_of]"
)
{
{
mock_str obj;
using trompeloeil::any_of;
using trompeloeil::eq;
REQUIRE_CALL(obj, overload(any_of<std::string>("", eq("foo"))));
obj.overload(std::string("foo"));
}
REQUIRE(reports.empty());
}

TEST_CASE_METHOD(
Fixture,
"C++14: none_of is true if no element matches",
"[C++14][matching][matchers][none_of]"
)
{
{
mock_str obj;
using trompeloeil::none_of;
using trompeloeil::eq;
REQUIRE_CALL(obj, str(none_of("bar", eq("foo"))));
obj.str("zoo");
}
REQUIRE(reports.empty());
}

TEST_CASE_METHOD(
Fixture,
"C++14: nane_of reports if any of the element matches",
"[C++14][matching][matchers][none_of]"
)
{
try {
mock_str obj;
using trompeloeil::none_of;
using trompeloeil::eq;
REQUIRE_CALL(obj, str(none_of("bar", eq("foo"))));
obj.str("bar");
FAIL("didn't throw");
}
catch (reported) {
REQUIRE(reports.size() == 1U);
auto re = R":(No match for call of str with signature void\(std::string\) with\.
param _1 == bar
Tried obj\.str\(none_of\(\"bar\", eq\(\"foo\"\)\)\) at [A-Za-z0-9_ ./:\]*:[0-9]*.*
Expected _1 to be none of \{ bar, == foo \}):";
INFO("report=" << reports.front().msg);
REQUIRE(std::regex_search(reports.front().msg, std::regex(re)));
}
}

TEST_CASE_METHOD(
Fixture,
"C++14: none_of can be disambiguated with explicit type",
"[C++14][matching][matchers][none_of]"
)
{
{
mock_str obj;
using trompeloeil::none_of;
using trompeloeil::eq;
REQUIRE_CALL(obj, overload(none_of<std::string>("bar", eq("foo"))));
obj.overload(std::string("zoo"));
}
REQUIRE(reports.empty());
}
//
TEST_CASE_METHOD(
Fixture,
"C++14: all_of is true if every element matches",
"[C++14][matching][matchers][all_of]"
)
{
{
C_ptr obj;
using trompeloeil::all_of;
using trompeloeil::ne;
using trompeloeil::eq;
REQUIRE_CALL(obj, ptr(all_of(ne(nullptr), *eq(3))));
int i = 3;
obj.ptr(&i);
}
REQUIRE(reports.empty());
}

TEST_CASE_METHOD(
Fixture,
"C++14: all_of reports if at least one element does not match",
"[C++14][matching][matchers][all_of]"
)
{
try {
C_ptr obj;
using trompeloeil::all_of;
using trompeloeil::eq;
using trompeloeil::ne;
REQUIRE_CALL(obj, ptr(all_of(ne(nullptr), *eq(3))));
int i = 4;
obj.ptr(&i);
FAIL("didn't throw");
}
catch (reported) {
REQUIRE(reports.size() == 1U);
auto re = R":(No match for call of ptr with signature void\(int\*\) with\.
param _1 == .*
Tried obj\.ptr\(all_of\(ne\(nullptr\), \*eq\(3\)\)\) at [A-Za-z0-9_ ./:\]*:[0-9]*.*
Expected _1 to be all of \{ != nullptr, == 3 \}):";
INFO("report=" << reports.front().msg);
REQUIRE(std::regex_search(reports.front().msg, std::regex(re)));
}
}

TEST_CASE_METHOD(
Fixture,
"C++14: all_of can be disambiguated with explicit type",
"[C++14][matching][matchers][all_of]"
)
{
{
C_ptr obj;
using trompeloeil::all_of;
using trompeloeil::eq;
using trompeloeil::ne;
REQUIRE_CALL(obj, coverload(all_of<const int*>(ne(nullptr), *eq(3))));
const int i = 3;
obj.coverload(&i);
}
REQUIRE(reports.empty());
}
//
// tests of parameter matching using typed matcher re

#if TROMPELOEIL_TEST_REGEX_FAILURES
Expand Down

0 comments on commit 7d3e5c6

Please sign in to comment.