109 KiB
Reference
- Notions
- Mock function
- Mock object
- Expectation
- Matcher
- _
ANY(
type)
MEMBER_IS(
member, matcher)
all_of(
values)
any_of(
values)
eq(
value)
ne(
value)
gt(
value)
ge(
value)
lt(
value)
le(
value)
none_of(
values)
re(
string)
range_includes(
*values)
range_is(
values)
range_all_of(
matcher)
range_any_of(
matcher)
range_none_of(
matcher)
range_is_permutation(
values)
range_starts_with(
values)
range_ends_with(
values)
*
matcher!
matcher
- Macros (alphabetical order)
ALLOW_CALL(
mock_object, func_name(parameter_list))
ANY(
type)
AT_LEAST(
number)
AT_MOST(
number)
CO_RETURN(
*expr `)CO_THROW(
*expr `)CO_YIELD(
*expr `)FORBID_CALL(
mock_object, func_name(parameter_list))
IMPLEMENT_CONST_MOCKn(
func_name)
`IMPLEMENT_MOCKn(
func_name)
`IMPLEMENT_STDMETHOD_MOCKn(
func_name)
`IN_SEQUENCE(
seq...)
LR_CO_RETURN(
expr)
LR_CO_THROW(
expr)
LR_CO_YIELD(
expr)
LR_RETURN(
expr)
LR_SIDE_EFFECT(
expr)
LR_THROW(
expr)
LR_WITH(
expr)
MAKE_CONST_MOCK(
func_name, signature)
MAKE_CONST_MOCKn(
func_name, signature)
MAKE_MOCK(
name, signature)
MAKE_MOCKn(
name, signature)
MAKE_STDMETHOD_MOCK(
name, signature)
MAKE_STDMETHOD_MOCKn(
name, signature)
NAMED_ALLOW_CALL(
mock_object, func_name(parameter_list))
NAMED_FORBID_CALL(
mock_object, func_name(parameter_list))
NAMED_REQUIRE_CALL(
mock_object, func_name(parameter_list))
NAMED_REQUIRE_DESTRUCTION(
mock_object)
REQUIRE_CALL(
mock_object, func_name(parameter_list))
REQUIRE_DESTRUCTION(
mock_object)
RETURN(
expr)
RT_TIMES(
limit)
SIDE_EFFECT(
expr)
THROW(
expr)
TIMES(
limit)
WITH(
expr)
- Types and Type Templates (alphabetical order)
trompeloeil::deathwatched<T>
trompeloeil::expectation
trompeloeil::expectation_violation
trompeloeil::lifetime_monitor
trompeloeil::matcher
trompeloeil::mock_interface<T>
trompeloeil::ok_reporter_func
trompeloeil::printer
trompeloeil::reporter_func
trompeloeil::sequence
trompeloeil::severity
trompeloeil::stream_tracer
trompeloeil::tracer
trompeloeil::typed_matcher<T>
- Functions and Function Templates
- Constants
Notions
Mock function
A mock function is a member function that is mocked with
MAKE_MOCK(name, signature)
,
MAKE_MOCKn(name, signature)
,
MAKE_CONST_MOCK(name, signature)
or
MAKE_CONST_MOCKn(name, signature)
.
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
MAKE_CONST_MOCK(cfunc, auto (std::string, int) -> int);
};
Above C
is a type that has two mock functions void func(int)
and
auto cfunc(std::string, int) const -> int
. With a mock object
of type C
it is possible to place expectations
on the functions func(...)
and cfunc(...)
.
Mock object
A mock object is an object of a type that has mock functions.
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
};
C obj;
Above, obj
is a mock object. It is possible to place
expectations on mock functions for the object
obj
.
Expectation
By default it is illegal to call mock functions. Expectations change that. Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
};
TEST(atest)
{
C mock_obj;
REQUIRE_CALL(mock_obj, func(3));
tested_function(mock_obj);
}
Above mock_obj
is a mock object with one
mock function void func(int)
.
The line REQUIRE_CALL(mock_obj, func(3))
places an
expectation that mock_obj.func(3)
is called before the end of the scope.
Unless tested_function(mock_obj)
calls mock_obj.func(3)
a violation is
reported.
The ways to set expectations are:
REQUIRE_CALL(
mock_object, func_name(parameter_list))
ALLOW_CALL(
mock_object, func_name(parameter_list))
FORBID_CALL(
mock_object, func_name(parameter_list))
NAMED_REQUIRE_CALL(
mock_object, func_name(parameter_list))
NAMED_ALLOW_CALL(
mock_object, func_name(parameter_list))
NAMED_FORBID_CALL(
mock_object, func_name(parameter_list))
Each NAMED variant returns an expectation as
std::unique_ptr<trompeloeil::expectation>
which can be
saved in variables for storage in test fixtures or other programmatic lifetime
control.
If expectations are not met by the time they go out or scope (or in case of the
NAMED variants, when the object held by the std::unique_ptr<>
is
destroyed) a violation is reported.
By default there is no order imposed on expectations. One way to impose order is
through their lifetimes. Another is by using
IN_SEQUENCE(...)
.
If there are several expectations that match the same call, they are tried in the reverse order of creation, and the first found match is accepted. In other words, the last created matching expectation is the one used.
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
};
using trompeloeil::_;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, func(_));
FORBID_CALL(mock_obj, func(3));
FORBID_CALL(mock_obj, func(4));
tested_function(mock_obj);
}
Above, the first expectation ALLOW_CALL(...)
matches
everything using the wildcard trompeloeil::_
, but the two
FORBID_CALL(...)
are created later and are thus matched
first. This means that if tested_function(...)
calls mock_obj.func(int)
with
5
, the two FORBID_CALL(...)
do not match, but the
ALLOW_CALL(...)
does, so the call is allowed. A call with
3
or 4
, results in a violation is report since a
FORBID_CALL(...)
is matched.
Matcher
Each parameter in the parameter list of an expectation can be
an exact value to match for equality (using operator==
,) or a matcher.
Matchers check a condition on the parameter value. Trompeloeil provides the
matchers
- _
ANY(
type)
MEMBER_IS(
member, matcher)
all_of(
values)
any_of(
values)
eq(
value)
ne(
value)
gt(
value)
ge(
value)
lt(
value)
le(
value)
none_of(
values)
re(
string)
range_includes(
values)
range_is(
values)
range_all_of(
matcher)
range_any_of(
matcher)
range_none_of(
matcher)
range_is_permutation(
values)
range_starts_with(
values)
range_ends_with(
values)
You can also provide your own matchers.
_
Used in the parameter list of an expectation, trompeloeil::_
matches any value of any type.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, int(int));
};
using trompeloeil::_;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, func(_))
.RETURN(_1 + 1);
test_function(&mock_obj);
}
Above, mock_obj.func()
is allowed to be called with any value, and it will
return 1 + the value provided.
If type information is needed, for example to disambiguate overloads, use
ANY(
type )
.
MEMBER_IS(
member, matcher )
Used in the parameter list of an expectation to match a member
of a passed value using a matcher. The matcher can be a value that can be
equality compared with the member, or a matcher like
gt(
value )
. This es especially useful together with the
matchers all_of(
values )
and
any_of(
values )
#include <trompeloeil/matcher/member_is.hpp>
Example:
struct xy
{
int x;
int y;
};
class C
{
public:
MAKE_MOCK1(func, void(xy));
};
TEST(atest)
{
C mock_obj;
REQUIRE_CALL(mock_obj, func(all_of(MEMBER_IS(&xy::x, gt(0)),
MEMBER_IS(&xy::y, 0))));
test_function(&mock_obj);
}
Above, the expectation matches only calls to mock_obj.fun(xy coord)
with
coord.x > 0 && coord.y == 0
.
ANY(
type )
Used in the parameter list of an expectation to match any value
of a specified type. This can be used as an alternative to
trompeloeil::_
when it is important to disambiguate between
overloads.
#include <trompeloeil/matcher/any.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
MAKE_MOCK2(func, void(std::string));
};
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, func(ANY(int)));
test_function(&mock_obj);
}
Above, any call to mock_obj.func(int)
is accepted, but calls to
mock_obj.func(std::string)
renders a violation report since there is no
matching expectation.
all_of(
values )
Used in the parameter list of an expectation to match a value with all of several provided. By default it matches any parameter type that supports comparison with the values, but an explicit type can be specified if needed for disambiguation. values can be any value that is equality comparable with the type, or other matchers that can be used with the type.
#include <trompeloeil/matcher/set_predicate.hpp>
Example:
class C
{
public:
MAKE_MOCK1(ifunc, void(int*));
MAKE_MOCK1(func, void(const char*));
MAKE_MOCK1(func, void(const std::string&));
};
using trompeloeil::ne;
using trompeloeil::eq;
using trompeloeil::all_of;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, ifunc(all_of(ne(nullptr), *eq(3))));
std::string expected = "foo";
REQUIRE_CALL(mock_obj, func(all_of<const char*>(ne(nullptr), expected)));
test_function(&mock_obj);
}
Above, the first expectation matches only calls to
mock_obj.ifunc(int*)
with a non-null pointer pointing to the value 3
. Any
call with a nullptr
or a pointer pointing to a value other than 3
renders
a violation report since no expectation matches.
The second expectation matches only calls to
mock_obj.func(const char*)
, with a C-string "foo"
.
any_of(
values )
Used in the parameter list of an expectation to match a value with any of several provided. By default it matches any parameter type that supports comparison with the values, but an explicit type can be specified if needed for disambiguation. values can be any value that is equality comparable with the type, or other matchers that can be used with the type.
#include <trompeloeil/matcher/set_predicate.hpp>
Example:
class C
{
public:
MAKE_MOCK1(ifunc, void(int*));
MAKE_MOCK1(func, void(const char*));
MAKE_MOCK1(func, void(const std::string&));
};
using trompeloeil::ne;
using trompeloeil::eq;
using trompeloeil::any_of;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, ifunc(any_of(nullptr, *eq(3))));
std::string expected = "foo";
REQUIRE_CALL(mock_obj, func(any_of<const char*>(nullptr, expected)));
test_function(&mock_obj);
}
Above, the first expectation matches only calls to
mock_obj.ifunc(int*)
with either a nullptr
, or a pointer to the value
3
. Any call with a non-null pointer pointing to a value other than 3
renders a violation report since no expectation matches.
The second expectation matches only calls to
mock_obj.func(const char*)
, with either nullptr
or a C-string "foo"
.
eq(
value )
Used in the parameter list of an expectation to match a
value equal to the one provided. By default it matches any parameter type
that supports operator==()
with the value, but an explicit type can be
specified if needed for disambiguation.
#include <trompeloeil/matcher/compare.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(int*));
MAKE_MOCK1(func, void(const char*));
MAKE_MOCK1(func, void(const std::string&));
};
using trompeloeil::eq;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, func(*eq(3)));
std::string expected = "foo";
REQUIRE_CALL(mock_obj, func(eq<const char*>(expected)));
test_function(&mock_obj);
}
Above, the first expectation matches only calls to
mock_obj.func(int*)
with a non-null pointer pointing to the value 3
. Any
call with a nullptr
or a pointer pointing to a value other than 3
renders
a violation report since no expectation matches.
The second expectation matches only calls to
mock_obj.func(const char*)
, with a C-string "foo"
.
ne(
value )
Used in the parameter list of an expectation to match a
value not equal to the one provided. By default it matches any parameter type
that supports operator!=()
with the value, but an explicit type can be
specified if needed for disambiguation.
#include <trompeloeil/matcher/compare.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(const char*));
MAKE_MOCK1(func, void(const std::string&));
};
using trompeloeil::ne;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, func(ne(nullptr)));
REQUIRE_CALL(mock_obj, func(ne<std::string>("")));
test_function(&mock_obj);
}
Above, the first expectation matches only calls to
mock_obj.func(const char*)
with non-null pointer. Any call with a nullptr
renders a violation report since no expectation matches.
The second expectation matches only calls to
mock_obj.func(const std::string&)
, with a non-empty string.
It is also possible to use *ne(val)
to match a pointer to a non-equal value.
gt(
value )
Used in the parameter list of an expectation to match a
value greater than the one provided. By default it matches any parameter type
that supports operator>()
with the value, but an explicit type can be
specified if needed for disambiguation.
#include <trompeloeil/matcher/compare.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(short));
MAKE_MOCK1(func, void(int));
MAKE_MOCK1(func, void(std::string));
};
using trompeloeil::gt;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, func(gt<short>(0)));
ALLOW_CALL(mock_obj, func(gt("foo")));
test_function(&mock_obj);
}
Above, the first expectation matches only calls to
mock_obj.func(short)
with positive values. Any call with 0 or negative, and
any calls to mock_obj.func(int)
renders a violation report since no
expectation matches.
The second expectation matches calls to
mock_obj.func(std::string)
, since
std::string
is
greater-than comparable with a string literal.
It is also possible to use *gt(val)
to match a pointer to a greater-than
value.
ge(
value )
Used in the parameter list of an expectation to match a
value greater than on equal to the one provided. By default it matches any
parameter type that supports operator>=()
with the value, but an explicit
type can be specified if needed for disambiguation.
#include <trompeloeil/matcher/compare.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
MAKE_MOCK1(func, void(short));
MAKE_MOCK1(func, void(std::string));
};
using trompeloeil::ge;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, func(ge<short>(0)));
REQUIRE_CALL(mock_obj, func(ge("foo")));
test_function(&mock_obj);
}
Above, the first expectation matches only calls to
mock_obj.func(short)
with zero or positive values. Any call with a negative
value renders a violation report since no expectation matches.
The second expectation matches only calls to
mock_obj.func(std::string)
, since
std::string
is
greater-than-or-equal-to comparable with string literal.
It is also possible to use *ge(val)
to match a pointer to a greater-than or
equal value.
lt(
value )
Used in the parameter list of an expectation to match a
value less than the one provided. By default it matches any parameter type
that supports operator<()
with the value, but an explicit type can be
specified if needed for disambiguation.
#include <trompeloeil/matcher/compare.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(long));
MAKE_MOCK1(func, void(int));
MAKE_MOCK1(func, void(const std::string&));
};
using trompeloeil::lt;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, func(lt<int>(0)));
REQUIRE_CALL(mock_obj, func(lt("foo")));
test_function(&mock_obj);
}
Above, the first expectation matches only calls to
mock_obj.func(int)
with negative values. Any call with 0 or positive
renders a violation report since no expectation matches.
The second expectation matches calls to
mock_obj.func(cost std::string&)
, since
std::string
is
less-than comparable with string a literal.
It is also possible to use *lt(val)
to match a pointer to a less-than value.
le(
value )
Used in the parameter list of an expectation to match a
value less than or equal to the one provided. By default it matches any
parameter type that supports operator<=()
with the value, but an explicit type
can be specified if needed for disambiguation.
#include <trompeloeil/matcher/compare.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
MAKE_MOCK1(func, void(short));
MAKE_MOCK1(func, void(const char*));
};
using trompeloeil::le;
using std::string_literals;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, func(le<short>(0)));
REQUIRE_CALL(mock_obj, func(le("foo"s)));
test_function(&mock_obj);
}
Above, first the expectation matches only calls to
mock_obj.func(short)
with zero or negative values. Any call with a positive
value renders a violation report since no expectation matches.
The second expectation matches calls to
mock_obj.func(const char*)
, since a c-string is less-than comparable
with a std::string
It is also possible to use *le(val)
to match a pointer to a less-than or
equal value.
none_of(
values )
Used in the parameter list of an expectation to ensure no match between a value and several provided. By default it matches any parameter type that supports comparison with the values, but an explicit type can be specified if needed for disambiguation. values can be any value that is equality comparable with the type, or other matchers that can be used with the type.
#include <trompeloeil/matcher/set_predicate.hpp>
Example:
class C
{
public:
MAKE_MOCK1(ifunc, void(int*));
MAKE_MOCK1(func, void(const char*));
MAKE_MOCK1(func, void(const std::string&));
};
using trompeloeil::ne;
using trompeloeil::eq;
using trompeloeil::none_of;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, ifunc(none_of(nullptr, *eq(3))));
std::string expected = "foo";
REQUIRE_CALL(mock_obj, func(none_of<const char*>(nullptr, expected)));
test_function(&mock_obj);
}
Above, the first expectation matches only calls to
mock_obj.ifunc(int*)
with a non-null pointer pointer to a value other than
3
. Any call with a nullptr
, or a pointer pointing to the value 3
renders a violation report since no expectation matches.
The second expectation matches only calls to
mock_obj.func(const char*)
, with a non-null pointer, pointing to a C-string
that is not "foo"
.
re(
string )
Used in the parameter list of an expectation to match a string with a regular expression.
#include <trompeloeil/matcher/re.hpp>
re()
exists in two flavours.
re(
string, flags...)
which can match both C-strings (char*
,const char*
) as well asC++
std::string
.re<type>(
string, flags...)
which can be used to disambiguate overloads.
For both versions, the string can be either std::string
or a C-string.
flags... can be
- empty
std::regex_constants::syntax_option_type
std::regex_constants::match_flag_type
std::regex_constants::syntax_option_type, std::regex_constants::match_flag_type
Regular expression matching is made with
std::regex_search()
Example:
class C
{
public:
MAKE_MOCK1(unique, void(std::string&));
MAKE_MOCK1(overloaded, void(const char*));
MAKE_MOCK1(overloaded, void(const std::string&));
};
using trompeloeil::re;
TEST(atest)
{
C mock_obj;
REQUIRE_CALL(mock_obj, unique(re("end$", std::regex_constants::icase)));
REQUIRE_CALL(mock_obj, overloaded(re<const char*>("end", std::regex_constants::match_not_eol)));
test_function(&mock_obj);
}
Above, test_function(&mock_obj)
must call mock_obj.unique()
with a string
case insensitively matching the regular expression /end$/
, and also call
mock_obj.overloaded(const char*)
with a regular expression matching
the regular expression /end/
.
It is also possible to use *re(string)
to match a pointer to a string with
a regular expression, or !re(string)
to allow only strings that do not match
a regular expression.
range_includes(
matchers )
Used in the parameter list of an expectation to match a range with has a set of matchers. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.
#include <trompeloeil/matcher/range.hpp>
range_includes
comes in two flavours:
range_includes(
matchers)
where matchers is one or several values or other matchers likere(
string)
range_includes(
values)
where values is a collection, e.g. astd::vector<>
or C-array, of values.
Example using matchers:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::list<int>&));
};
using trompeloeil::gt;
using trompeloeil::range_includes;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, vfunc(range_includes(gt(2), 1)));
REQUIRE_CALL(mock_obj, ofunc(range_includes<std::list<int>>(1,2,3)));
test_function(&mock_obj);
}
Above, first the expectation matches only calls to
mock_obj.vfunc(const std::vector<int>&)
which has at least one element
== 1
, and at least one element > 2
. Any call with a different set of
values renders a violation report since no expectation
matches.
The second expectation matches calls to
mock_obj.ofunc(const std::list<int>&)
with at least the values
{ 1, 2, 3 }
(in any order).
Example using a C-array of values:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
};
using trompeloeil::range_includes;
TEST(atest)
{
C mock_obj;
int values[] {2, 1 };
ALLOW_CALL(mock_obj, vfunc(range_includes(values)));
test_function(&mock_obj);
}
The expectation only matches calls to mock_obj.vfunc()
with a vector that
holds at least one elemend with the value 1, and at least one element with
the value 2.
range_is(
matchers )
Used in the parameter list of an expectation to match a range with a set of matchers. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.
#include <trompeloeil/matcher/range.hpp>
range_is
comes in two flavours:
range_is(
matchers)
where matchers is one or several values or other matchers likere(
string)
range_is(
values)
where values is a collection, e.g. astd::vector<>
or C-array, of values.
Example using matchers:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::list<int>&));
};
using trompeloeil::le;
using trompeloeil::range_is;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, vfunc(range_is(1, 3, le(0))));
REQUIRE_CALL(mock_obj, ofunc(range_is<std::list<int>>(1,2,3)));
test_function(&mock_obj);
}
Above, first the expectation matches only calls to
mock_obj.vfunc(const std::vector<int>&)
with the values { 1, 3, x }
,
where x <= 0
. Any call with a different set of values
renders a violation report since no expectation matches.
The second expectation matches calls to
mock_obj.ofunc(const std::list<int>&)
with the values { 1, 2, 3 }
.
Example using C-array of values:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
};
using trompeloeil::range_is;
TEST(atest)
{
C mock_obj;
int expected[] { 1, 2, 3 };
ALLOW_CALL(mock_obj, vfunc(range_is(expected)));
test_function(&mock_obj);
}
The expectation only matches calls to mock_obj.vfunc()
with a vector holding exactly { 1, 2, 3 }.
range_all_of(
matcher )
Used in the parameter list of an expectation to match each element in a range to a matcher or value. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.
#include <trompeloeil/matcher/range.hpp>
Example:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::list<int>&));
};
using trompeloeil::gt;
using trompeloeil::range_all_of;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, vfunc(range_all_of(gt(0))));
REQUIRE_CALL(mock_obj, ofunc(range_all_of<std::list<int>>(gt(0))));
test_function(&mock_obj);
}
Above, first the expectation matches only calls to
mock_obj.vfunc(const std::vector<int>&)
with values > 0
,
Any call with a different set of values
renders a violation report since no expectation matches.
The second expectation matches calls to
mock_obj.ofunc(const std::list<int>&)
with values > 0
.
The matcher range_all_of
always matches an empty range.
range_any_of(
matcher )
Used in the parameter list of an expectation to match each element in a range to a matcher or value. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.
#include <trompeloeil/matcher/range.hpp>
Example:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::list<int>&));
};
using trompeloeil::gt;
using trompeloeil::range_any_of;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, vfunc(range_any_of(gt(0))));
REQUIRE_CALL(mock_obj, ofunc(range_any_of<std::list<int>>(gt(0))));
test_function(&mock_obj);
}
Above, first the expectation matches only calls to
mock_obj.vfunc(const std::vector<int>&)
with at least one values > 0
,
Any call with a different set of values
renders a violation report since no expectation matches.
The second expectation matches calls to
mock_obj.ofunc(const std::list<int>&)
with at least one value > 0
.
The matcher range_any_of
does never match an empty range.
range_none_of(
matcher )
Used in the parameter list of an expectation to match each element in a range to a matcher or value. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.
#include <trompeloeil/matcher/range.hpp>
Example:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::list<int>&));
};
using trompeloeil::lt;
using trompeloeil::range_none_of;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, vfunc(range_none_of(0)));
REQUIRE_CALL(mock_obj, ofunc(range_none_of<std::list<int>>(lt(0))));
test_function(&mock_obj);
}
Above, first the expectation matches only calls to
mock_obj.vfunc(const std::vector<int>&)
where none of the values are 0
,
Any call with a at least one value == 0
renders a violation report since
no expectation matches.
The second expectation matches calls to
mock_obj.ofunc(const std::list<int>&)
where none of the values are < 0
.
The matcher range_none_ofl
always matches an empty range.
range_is_permutation(
matchers )
Used in the parameter list of an expectation to match a range with a set of matchers without regard to order. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.
#include <trompeloeil/matcher/range.hpp>
range_is_permutation
comes in two flavours:
range_is_permutation(
matchers)
where matchers is one or several values or other matchers likere(
string)
range_is_permutation(
values)
where values is a collection, e.g. astd::vector<>
or C-array, of values.
Example using matchers:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::list<int>&));
};
using trompeloeil::le;
using trompeloeil::range_is_permutation;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, vfunc(range_is_permutation(le(0), 1, 3)));
REQUIRE_CALL(mock_obj, ofunc(range_is_permutation<std::list<int>>(1,2,3)));
test_function(&mock_obj);
}
Above, first the expectation matches only calls to
mock_obj.vfunc(const std::vector<int>&)
with some permutation of the values
{ 1, 3, x }
, where x <= 0
. Any call with a different set of values
renders a violation report since no expectation matches.
The second expectation matches calls to
mock_obj.ofunc(const std::list<int>&)
with a permutation of the values
{ 1, 2, 3 }
.
NOTE! Avoid using range_is_permutation
with relational matchers like
gt(
value )
. In order to work with input-ranges, it
uses a greedy one-pass algorithm, which may reach different results
depending on the order in which the elements are matched. E.g.
range_is_permutation(gt(0), gt(1), gt(2))
may or may not match a range
{3,2,1}
.
Example using a C-array of values:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
};
using trompeloeil::range_is_permutation;
TEST(atest)
{
C mock_obj;
int values[] { 1, 2, 3 };
ALLOW_CALL(mock_obj, vfunc(range_is_permutation(values)));
test_function(&mock_obj);
}
This only allows calls to mock_obj.vfunc()
with a vector holding the values
1, 2, 3, in any order.
range_starts_with(
matchers )
Used in the parameter list of an expectation to match the first values in a range to a set of matchers. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.
#include <trompeloeil/matcher/range.hpp>
range_starts_with
comes in two flavours:
range_starts_with(
matchers)
where matchers is one or several values or other matchers likere(
string)
range_starts_with(
values)
where values is a collection, e.g. astd::vector<>
or C-array, of values.
Example using matchers:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::list<int>&));
};
using trompeloeil::le;
using trompeloeil::range_starts_with;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, vfunc(range_starts_with(1, le(0))));
REQUIRE_CALL(mock_obj, ofunc(range_starts_with<std::list<int>>(1,2)));
test_function(&mock_obj);
}
Above, first the expectation matches only calls to
mock_obj.vfunc(const std::vector<int>&)
with a vector holding at
least two elements, starting with { 1, x, }
, where x <= 0
.
Any call with a different set of values renders a violation report
since no expectation matches.
The second expectation matches calls to
mock_obj.ofunc(const std::list<int>&)
with at least two values,
starting with { 1, 2 }
.
Example using a C-array with values:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
};
using trompeloeil::range_starts_with;
TEST(atest)
{
C mock_obj;
int first_values[]{1,2};
ALLOW_CALL(mock_obj, vfunc(range_starts_with(first_values)));
test_function(&mock_obj);
}
The example above matches only calls to mock_obj.vfunc()
with a vector
which starts with the values {1, 2}.
range_ends_with(
matchers )
Used in the parameter list of an expectation to match the last values in a range to a set of matchers. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.
#include <trompeloeil/matcher/range.hpp>
range_ends_with
comes in two flavours:
range_ends_with(
matchers)
where matchers is one or several values or other matchers likere(
string)
range_ends_with(
values)
where values is a collection, e.g. astd::vector<>
or C-array, of values.
Example using matchers:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::vector<int>&));
MAKE_MOCK1(ofunc, void(const std::list<int>&));
};
using trompeloeil::le;
using trompeloeil::range_ends_with;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, vfunc(range_ends_with(1, le(0))));
REQUIRE_CALL(mock_obj, ofunc(range_ends_with<std::list<int>>(1,2)));
test_function(&mock_obj);
}
Above, first the expectation matches only calls to
mock_obj.vfunc(const std::vector<int>&)
with a vector holding at
least two elements, ending with { 1, x, }
, where x <= 0
.
Any call with a different set of values renders a violation report
since no expectation matches.
The second expectation matches calls to
mock_obj.ofunc(const std::list<int>&)
with at least two values,
ending with { 1, 2 }
.
Example using a C-array of values:
class C
{
public:
MAKE_MOCK1(vfunc, void(const std::vector<int>&));
};
using trompeloeil::range_ends_with;
TEST(atest)
{
C mock_obj;
int tail[]{2,1,0};
ALLOW_CALL(mock_obj, vfunc(range_ends_with(tail)));
test_function(&mock_obj);
}
The example above only matches calls to mock_obj.vfunc()
with a vector with
2,1,0 as the last elements.
*
matcher
Used in the parameter list of an expectation together with a
matcher, to match a value pointed to by a pointer. A
nullptr
value fails the
matcher.
#include <trompeloeil/matcher/deref.hpp>
Example:
struct C {
MAKE_MOCK1(func, void(int*));
};
using trompeloeil::eq; // matching equal values
TEST(atest)
{
C mock_obj;
REQUIRE_CALL(mock_obj, func(*eq(3)));
test_function(&mock_obj);
}
Above, test_function(&mock_obj)
must call mock_obj.func()
with a pointer
to the value 3
.
!
matcher
Used in the parameter list of an expectation together with a matcher, to negate a matcher, i.e. to fail what the matcher allows, and to allow what the matcher fails.
#include <trompeloeil/matcher/not.hpp>
Example:
struct C {
MAKE_MOCK1(func, void(const std::string&));
};
using trompeloeil::re; // matching regular expressions
TEST(atest)
{
C mock_obj;
REQUIRE_CALL(mock_obj, func(!re("^foo")));
test_function(&mock_obj);
}
Above, test_function(&mock_obj)
must call mock_obj.func()
with a string
that does not begin with "foo"
.
Macros
ALLOW_CALL(
mock_object, func_name(parameter_list))
Make an expectation that mock_object.func_name(parameter_list) may be called zero or more times until the end of the surrounding scope. parameter_list may contain exact values or matchers that describes matching calls.
This is the same as
REQUIRE_CALL(...)
.TIMES(
0,infinity )
.
#include <trompeloeil/mock.hpp>
Matches any number of times, but is not required to match. (actually the limit is 0..~0ULL, but that is for all practical purposes "infinity")
Example:
class C
{
public:
MAKE_MOCK1(func, int(int));
};
using trompeloeil::_;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, func(_))
.RETURN(_1 + 1);
test_function(&mock_obj);
}
Above ALLOW_CALL(mock_obj, func(_))
places an expectation that
mock_obj.func()
may be called any number of times with any parameter value
and will always return the parameter value + 1. test_function(...)
is allowed to call mock_obj.func()
any number of times (including no call at
all).
The expectation is valid until the end of the scope, which in the example above
is until after the return from test_function(...)
.
See also NAMED_ALLOW_CALL(...)
which creates an
expectation as a
std::unique_ptr<trompeloeil::expectation>
which can be
stored in test fixtures or otherwise have its lifetime programmatically controlled.
ANY(
type )
A matcher for use in the parameter list of an
expectation to disambiguate overloaded functions on type when
the exact value is unimportant. See the matcher ANY(
type )
above.
#include <trompeloeil/matcher/any.hpp>
AT_LEAST(
number )
Used in TIMES(...)
to set the range number..infinity.
number must be
constexpr
.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
};
using trompeloeil::_;
TEST(atest)
{
C mock_obj;
REQUIRE_CALL(mock_obj, func(_))
.TIMES(AT_LEAST(3));
tested_function(&mock_obj);
}
Above, the line TIMES(
AT_LEAST(3))
modifies the
expectation such that mock_obj.func() must be called 3 times
or more, before the end of the scope, or a violation is reported.
In reality the upper limit is ~0ULL, but that is for all practical purposes "infinity".
AT_MOST(
number )
Used in TIMES(...)
to set the range 0..number.
number must be
constexpr
.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
};
using trompeloeil::_;
TEST(atest)
{
C mock_obj;
REQUIRE_CALL(mock_obj, func(_))
.TIMES(AT_MOST(3));
tested_function(&mock_obj);
}
Above, the line TIMES(
AT_MOST(3))
modifies the
expectation such that mock_obj.func() must be called 3 times
or less (including no call at all) before the end of the scope, or a violation
is reported.
CO_RETURN(
expr )
Used in expectations to set the return value from a coroutine.
Note that when SIDE_EFFECT(...)
and
LR_SIDE_EFFECT(...)
are executed depends on the behaviour of the
coroutine promise type. This code may alter out-parameters.
#include <trompeloeil/coro.hpp>
Coroutines are supported if the compiler defines the
__cpp_impl_coroutines
feature test macro.
NOTE! Be very extra careful with lifetime issues when dealing with coroutines.
CO_THROW(
expr )
Used in expectations to throw an exception from a coroutine.
Note that when any SIDE_EFFECT(...)
and
LR_SIDE_EFFECT(...)
are executed depends on the behaviour of the
coroutine promise type. This code may alter out-parameters.
#include <trompeloeil/coro.hpp>
Coroutines are supported if the compiler defines the
__cpp_impl_coroutines
feature test macro.
NOTE! Be very extra careful with lifetime issues when dealing with coroutines.
CO_YIELD(
expr )
Used in expectations with a coroutine type that can
co_yield
.
You can add several CO_YIELD
to the same expectation, and the values will
be yielded one at the time, in the order they are listed. Note that
CO_RETURN(
expr )
or
LR_CO_RETURN(
expr )
is still needed.
See also LR_CO_YIELD(
expr ]
#include <trompeloeil/coro.hpp>
Coroutines are supported if the compiler defines the
__cpp_impl_coroutines
feature test macro.
NOTE! Be very extra careful with lifetime issues when dealing with coroutines.
FORBID_CALL(
mock_object, func_name(parameter_list))
Make an expectation that mock_object.func_name(parameter_list) must not be called until the end of the scope. parameter_list may contain exact values or matchers that describes matching calls.
This is the same as
REQUIRE_CALL(...)
.TIMES(
0 )
,
making any matching call an error. This is often done in a narrow scope
where the wider scope would allow the call. LR_RETURN(...)
,
RETURN(...)
, LR_THROW(...)
and
THROW(...)
are illegal in a FORBID_CALL(...)
.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
};
using trompeloeil::_;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, func(_));
tested_function(1, &mock_obj);
{
FORBID_CALL(mock_obj, func(2));
tested_function(2, &mock_obj);
}
tested_function(3, &mock_obj);
}
Above, the mock function C::func(int) may be called with any value for mock_obj, except in the scope of the tested_function(2, &mock_obj), where mock_obj.func(2) would lead to a violation being reported. At tested_function(3, &mock_obj) any value is allowed again.
See also NAMED_FORBID_CALL(...)
which creates an
expectation as a
std::unique_ptr<trompeloeil::expectation>
which can be
stored in test fixtures or otherwise have its lifetime programmatically controlled.
IMPLEMENT_CONST_MOCKn(
func_name {, specifiers } )
Make a const
mock function implementation of the
virtual
function named func_name from the inherited interface. This macro
is only usable with virtual
non-final
functions, and only when used with
mock_interface<T>
, where T
is the interface.
specifiers is an optional list which may include attributes or specifiers like
noexcept
.
#include <trompeloeil/mock.hpp>
Example:
class I
{
public:
virtual ~I() = default;
virtual int func(int, const std::vector<int>&)) const = 0;
};
class C : public trompeloeil::mock_interface<I>
{
public:
IMPLEMENT_CONST_MOCK2(func);
};
Above, class C
will effectively become:
class C : public trompeloeil::mock_interface<I>
{
public:
int func(int, const std::vector<int>&) const override;
};
It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.
NOTE! IMPLEMENT_CONST_MOCKn(...)
cannot handle overloaded functions.
See also IMPLEMENT_MOCKn(...)
for non-const
member functions.
See also MAKE_MOCK(...)
,
MAKE_MOCKn(...)
,
MAKE_CONST_MOCK(...)
and
MAKE_CONST_MOCKn(...)
for making mock implementations
of any member functions.
IMPLEMENT_MOCKn(
func_name {, specifiers } )
Make a non-const
mock function implementation of the
virtual
function named func_name from the inherited interface. This macro
is only usable with virtual
non-final
functions, and only when used with
mock_interface<T>
, where T
is the interface.
specifiers is an optional list which may include attributes or specifiers like
noexcept
.
#include <trompeloeil/mock.hpp>
Example:
class I
{
public:
virtual ~I() = default;
virtual int func(int, const std::vector<int>&)) = 0;
};
class C : public trompeloeil::mock_interface<I>
{
public:
IMPLEMENT_MOCK2(func1);
};
Above, class C
will effectively become:
class C : public trompeloeil::mock_interface<I>
{
public:
int func(int, const std::vector<int>&) override;
};
It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.
NOTE! IMPLEMENT_MOCKn(...)
cannot handle overloaded functions.
See also IMPLEMENT_CONST_MOCKn(...)
for const
member functions.
See also MAKE_CONST_MOCKn(...)
for const
member functions.
IMPLEMENT_STDMETHOD_MOCKn(
func_name {, specifiers } )
Make a STDMETHODCALLTYPE
mock function implementation of the
virtual
function named func_name from the inherited interface. This macro
is only usable with virtual
non-final
functions, and only when used with
mock_interface<T>
, where T
is the interface.
specifiers is an optional list which may include attributes or specifiers like
noexcept
.
#include <trompeloeil/mock.hpp>
Example:
class I
{
public:
virtual ~I() = default;
virtual int STDMETHODCALLTYPE func(int, const std::vector<int>&)) const = 0;
};
class C : public trompeloeil::mock_interface<I>
{
public:
IMPLEMENT_STDMETHOD_MOCK2(func);
};
Above, class C
will effectively become:
class C : public trompeloeil::mock_interface<I>
{
public:
int STDMETHODCALLTYPE func(int, const std::vector<int>&) const override;
};
It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.
NOTE! IMPLEMENT_STDMETHOD_MOCKn(...)
cannot handle overloaded functions.
NOTE! IMPLEMENT_STDMETHOD_MOCKn(...)
only works on Windows.
See also MAKE_STDMETHOD_MOCKn(...)
IN_SEQUENCE(
seq... )
Where seq... is one or more instances of trompeloeil::sequence
. Impose an
order in which expectations and destruction of
deathwatched_type
objects must match.
Several sequences can be parallel and interleaved. A sequence for an
expectation can move forward to the next once the lower
limit from TIMES(...)
is reached (defaults to 1). This means
that if the lower limit is 0 (see ALLOW_CALL(...)
), the
expectation may be skipped in the sequence.
#include <trompeloeil/sequence.hpp>
Example:
class Mock
{
public:
MAKE_MOCK1(func, void(int));
MAKE_MOCK1(func, void(const std::string&));
};
class ephemeral
{
public:
virtual ~ephemeral() {};
};
TEST(atest)
{
Mock m[2];
auto e = new trompeloeil::deathwatched<ephemeral>;
trompeloeil::sequence seq1, seq2;
REQUIRE_CALL(m[0], func(ANY(int))
.IN_SEQUENCE(seq1, seq2);
REQUIRE_CALL(m[0], func(ANY(const std::string&))
.IN_SEQUENCE(seq1);
REQUIRE_CALL(m[1], func(ANY(const std::string&))
.IN_SEQUENCE(seq2);
REQUIRE_CALL(m[1], func(ANY(int))
.IN_SEQUENCE(seq1, seq2);
REQUIRE_DESTRUCTION(*e)
.IN_SEQUENCE(seq1, seq2);
tested_func(&m[0], &m[1], e);
}
All sequence objects are listed in the first REQUIRE_CALL(...)
,
thus it must be the first expectation matched. Likewise all
sequences are listed in the last
REQUIRE_CALL(...)
, so it must be last
expectation matched. The intermediate
expectations has one sequence object each, thus they have no
matching order imposed between them. Last of all is the
REQUIRE_DESTRUCTION(...)
, which also lists
all sequence objects and must happen after all other
expectations are fulfilled.
The above allows the following two sequences only.
m[0].func(int)
->m[0].func(string)
->m[1].func(string)
->m[1].func(int)
->delete e
m[0].func(int)
->m[1].func(string)
->m[0].func(string)
->m[1].func(int)
->delete e
Any other sequence of calls renders a violation report.
Note that .IN_SEQUENCE()
in combination with .TIMES(...)
is
greedy. It will stay on on the same expectation as long as it matches, and
will leave for the next step in the sequence only when the upper bound from
.TIMES(...)
is reached, or a different expectation matches.
Example:
class Mock
{
public:
MAKE_MOCK1(func, void(int));
};
TEST(a_test)
{
Mock m;
trompeloeil::sequence seq;
REQUIRE_CALL(m, func(0))
.IN_SEQUENCE(seq)
.TIMES(1, 5);
ALLOW_CALL(m, func(0))
.IN_SEQUENCE(seq)
.SIDE_EFFECT(std::cout << "extra\n");
REQUIRE_CALL(m, func(1))
.IN_SEQUENCE(seq);
test_func(m);
}
The expectation REQUIRE_CALL(m, func(0))
stays in effect until either matched
5 times, or a call to m.func(1)
has been made. After a call to m.func(1)
,
no call to m.func(0)
is allowed.
The function test_func()
must call m.func(0)
at least once, and end with
m.func(1)
. If m.func(0)
is called more than 5 times, each call prints
"extra"
on std::cout
.
LR_CO_RETURN(
expr )
Used in expectations to set the return value from a coroutine.
Note that when any SIDE_EFFECT(...)
and
LR_SIDE_EFFECT(...)
are executed depends on the behaviour of the
coroutine promise type. This code may alter out-parameters.
#include <trompeloeil/coro.hpp>
Coroutines are supported if the compiler defines the
__cpp_impl_coroutines
feature test macro.
NOTE! Any named local objects named in expr are captured by reference so lifetime management is important.
NOTE! Be very extra careful with lifetime issues when dealing with coroutines.
LR_CO_THROW(
expr )
Used in expectations to throw an exception from a coroutine.
Note that when any SIDE_EFFECT(...)
and
LR_SIDE_EFFECT(...)
are executed depends on the behaviour of the
coroutine promise type. This code may alter out-parameters.
#include <trompeloeil/coro.hpp>
Coroutines are supported if the compiler defines the
__cpp_impl_coroutines
feature test macro.
NOTE! Any named local objects named in expr are captured by reference so lifetime management is important.
NOTE! Be very extra careful with lifetime issues when dealing with coroutines.
LR_CO_YIELD(
expr )
Used in expectations with a coroutine type that can
co_yield
.
You can add several LR_CO_YIELD
to the same expectation, and the values will
be yielded one at the time, in the order they are listed. Note that
CO_RETURN(
expr )
or
LR_CO_RETURN(
expr )
is still needed.
See also CO_YIELD(
expr ]
#include <trompeloeil/coro.hpp>
Coroutines are supported if the compiler defines the
__cpp_impl_coroutines
feature test macro.
NOTE! Any named local objects named in expr are captured by reference so lifetime management is important.
NOTE! Be very extra careful with lifetime issues when dealing with coroutines.
LR_RETURN(
expr )
Used in expectations to set the return value after having
evaluated every SIDE_EFFECT(...)
and
LR_SIDE_EFFECT(...)
.
For void
functions LR_RETURN(...)
is illegal. For non-void
functions
exactly one of RETURN(...)
, LR_RETURN(...)
,
LR_THROW(...)
or THROW(...)
is required.
expr may refer to parameters in the call with their positional names _1
,
_2
, etc.
This code may alter out-parameters.
#include <trompeloeil/mock.hpp>
If you need to return an
lvalue-reference,
to a variable, use
std::ref(value)
or
std::cref(value)
for it, or just enclose the value in an extra parenthesis, like this
.LR_RETURN((value))
.
NOTE! Any named local objects named in expr are captured by reference so lifetime management is important.
Example:
class C
{
public:
MAKE_MOCK1(func, int&(unsigned));
};
TEST(atest)
{
C mock_obj;
int rv = 3;
ALLOW_CALL(mock_obj, func(0))
.LR_RETURN(std::ref(rv)); // reference to captured local variable
rv = 4;
test_func(&mock_obj);
}
Above, the LR_RETURN(...)
clause tells matching calls of
mock_obj.func(...)
to return a reference to the local variable rv
.
Since LR_RETURN(...)
accesses local variables by reference, the value
of the returned reference will be 4 if called from within test_func(...)
.
See also RETURN(...)
which accesses copies of local variables.
LR_SIDE_EFFECT(
expr )
Used in expectations to cause side effects for matching calls.
expr is only evaluated when all WITH(...)
and
LR_WITH(...)
clauses are matched. expr may refer to
parameters in the call with their positional names _1
, _2
, etc. This code
may alter out-parameters. Several LR_SIDE_EFFECT(...)
and
SIDE_EFFECT(...)
clauses can be added to a single expectation, and they are
evaluated in order.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(unsigned));
};
TEST(atest)
{
C mock_obj;
unsigned sum = 0;
ALLOW_CALL(mock_obj, func(ANY(unsigned))
.LR_SIDE_EFFECT(sum += _1);
tested_func(&mock_obj);
std::cout << "parameter sum=" << sum << "\n";
}
Above, tested_func(&mock_obj)
is allowed to call C::func(int)
any
number of times on mock_obj
. Each time a side effect is that the local
variable sum
gets the parameter value added to it. Since
LR_SIDE_EFFECT(...)
refers to sum
by reference, it is the actual
local variable that is changed is every call.
See also SIDE_EFFECT(...)
which accesses copies of local
objects.
LR_THROW(
expr )
Used in expectations to throw after having evaluated every
SIDE_EFFECT(...)
and
LR_SIDE_EFFECT(...)
for a matching call.
expr may refer to parameters in the call with their positional names _1
,
_2
, etc. This code may alter out-parameters. It is not legal to combine
LR_THROW(...)
with any of THROW(...)
,
LR_RETURN(...)
or RETURN(...)
. Named local
objects are accessed by reference so lifetime management is important.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(unsigned));
};
TEST(atest)
{
C mock_obj;
const char* what="";
ALLOW_CALL(mock_obj, func(3))
.LR_THROW(std::invalid_argument(what));
what = "nonsense";
tested_func(&mock_obj);
}
Above, LR_THROW(std::invalid_argument(what))
will refer to the C-string
what
with the value it has at the time of a call to mock_obj.func(3)
, i.e.
"nonsense"
if tested_func()
does the call.
See also THROW(...)
which accesses copies of local objects.
LR_WITH(
expr )
Used with expectations to add further conditions for a
matching call. Typically used when matchers are used for the
parameters, and often when the condition requires several parameter values
together.
expr can refer to parameters in the call with their positional names _1
,
_2
, etc. Even if the function signature has parameters as non-const
references, they are immutable in this context. Several LR_WITH(...)
and WITH(...)
clauses can be added to a single expectation and
they are tried in the order they are added until one has failed, or they all
have passed.
Named local objects are accessed by reference so lifetime management is important.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(const char*));
};
using trompeloeil::_;
TEST(atest)
{
C mock_obj;
const char buff[] = "string";
REQUIRE_CALL(mock_obj, func(_))
.LR_WITH(_1 == buff);
tested_func(buff, &mock_obj);
}
Above, LR_WITH(_1 == buff)
checks the condition that the const char*
parameter is the same pointer value as the address to the local array buff
.
NOTE! It is legal, but a very bad idea, to modify global/static objects in
LR_WITH(...)
. If several expectations could match and
are disambiguated by LR_WITH(...)
and WITH(...)
the
global/static objects will be modified also by those
expectations that do not match.
See also WITH(...)
which accesses copies of local objects.
MAKE_CONST_MOCK(
func_name, signature {, specifiers } )
Make a const
mock function named func_name. It is a good
idea for this to implement a pure virtual function from an interface, but
it is not a requirement. n
is the number of parameters in signature.
specifiers is an optional list which may include attributes or specifiers like
override
or
noexcept
.
Because of limitations in how the preprocessor works, signature must be written with trailing return type syntax.
#include <trompeloeil/mock.hpp>
Example:
class I
{
public:
virtual ~I() = default;
virtual auto func1(int, const std::vector<int>&)) const -> int = 0;
};
class C
{
public:
MAKE_CONST_MOCK(func1, auto (int, const std::vector<int>&) -> int, override);
MAKE_CONST_MOCK(func2, auto (std::string) -> int);
};
Above, class C
will effectively become:
class C : public I
{
public:
auto func1(int, const std::vector<int>&) const -> int override;
auto func2(std::string) const -> int;
};
It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.
Note! The preprocessor is limited and can only handle nullary functions, i.e. functions that do not accept any arguments, in some cases.
-
MSVC handles nullary functions when compiling with
/Zc:preprocessor
with MSVC 19.40 (VS 17.10) or later. -
Gcc and Clang always handles nullary functions when compiling with C++20 or later, and when enabling a gcc extension by defining the macro
TROMPELOEIL_HAS_GCC_PP
before#include
:ing the trompeloeil headers, and compiling with-std=gnu++11
,-std=gnu++14
or-std=gnu++17
.
Otherwise, use MAKE_CONST_MOCK0(...)
to explicitly
define a nullary mock function.
See also MAKE_MOCK(...)
for non-const
member functions, and MAKE_CONST_MOCKn(...)
for
explicit function arity.
MAKE_CONST_MOCKn(
func_name, signature {, specifiers } )
Make a const
mock function named func_name. It is a good
idea for this to implement a pure virtual function from an interface, but
it is not a requirement. n
is the number of parameters in signature.
specifiers is an optional list which may include attributes or specifiers like
override
or
noexcept
.
#include <trompeloeil/mock.hpp>
Example:
class I
{
public:
virtual ~I() = default;
virtual int func1(int, const std::vector<int>&)) const = 0;
};
class C
{
public:
MAKE_CONST_MOCK2(func1, int(int, const std::vector<int>&), override);
MAKE_CONST_MOCK1(func2, int(std::string));
};
Above, class C
will effectively become:
class C : public I
{
public:
int func1(int, const std::vector<int>&) const override;
int func2(std::string) const;
};
It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.
See also MAKE_MOCKn(...)
for non-const
member functions and MAKE_CONST_MOCK(...)
` for
implicit function arity deduction.
MAKE_MOCK(
func_name, signature {, specifiers } )
Make a non-const mock function named func_name. It is a
good idea for this to implement a pure virtual function from an interface, but
it is not a requirement. n
is the number of parameters in signature.
specifiers is an optional list which may include attributes or specifiers like
override
or
noexcept
.
Because of limitations in how the preprocessor works, signature must be written with trailing return type syntax.
#include <trompeloeil/mock.hpp>
Example:
class I
{
public:
virtual ~I() = default;
virtual auto func1(int, const std::vector<int>&)) -> int = 0;
};
class C : public I
{
public:
MAKE_MOCK(func1, auto (int, const std::vector<int>&) -> int, override);
MAKE_MOCK(func2, auto (std::string) -> int);
};
Above, class C
will effectively become:
class C : public I
{
public:
auto func1(int, const std::vector<int>&) -> int override;
auto func2(std::string) -> int;
};
It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.
Note! The preprocessor is limited and can only handle nullary functions, i.e. functions that do not accept any arguments, in some cases.
-
MSVC handles nullary functions when compiling with
/Zc:preprocessor
with MSVC 19.40 (VS 17.10) or later. -
Gcc and Clang always handles nullary functions when compiling with C++20 or later, and when enabling a gcc extension by defining the macro
TROMPELOEIL_HAS_GCC_PP
before#include
:ing the trompeloeil headers, and compiling with-std=gnu++11
,-std=gnu++14
or-std=gnu++17
.
Otherwise, use MAKE_MOCK0(...)
to explicitly
define a nullary mock function.
See also MAKE_CONST_MOCK(...)
for const
member functions and MAKE_MOCKn(...)
for explicit
function arity.
MAKE_MOCKn(
func_name, signature {, specifiers } )
Make a non-const mock function named func_name. It is a
good idea for this to implement a pure virtual function from an interface, but
it is not a requirement. n
is the number of parameters in signature.
specifiers is an optional list which may include attributes or specifiers like
override
or
noexcept
.
#include <trompeloeil/mock.hpp>
Example:
class I
{
public:
virtual ~I() = default;
virtual int func1(int, const std::vector<int>&)) = 0;
};
class C : public I
{
public:
MAKE_MOCK2(func1, int(int, const std::vector<int>&), override);
MAKE_MOCK1(func2, int(std::string));
};
Above, class C
will effectively become:
class C : public I
{
public:
int func1(int, const std::vector<int>&) override;
int func2(std::string);
};
It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.
See also MAKE_CONST_MOCKn(...)
for const
member functions and MAKE_MOCK(...)
` for implicit function
arity deduction.
MAKE_STDMETHOD_MOCK(
func_name, signature {, specifiers } )
Make a STDMETHODCALLTYPE mock function named func_name. It is a
good idea for this to implement a pure virtual function from an interface, but
it is not a requirement. n
is the number of parameters in signature.
specifiers is an optional list which may include attributes or specifiers like
override
or
noexcept
.
Because of limitations in how the preprocessor works, signature must be written with trailing return type syntax.
#include <trompeloeil/mock.hpp>
Example:
class I
{
public:
virtual ~I() = default;
virtual auto STDMETHODCALLTYPE func1(int, const std::vector<int>&)) -> int = 0;
};
class C : public I
{
public:
MAKE_STDMETHOD_MOCK(func1, auto (int, const std::vector<int>&) -> int, override);
MAKE_STDMETHOD_MOCK(func2, auto (std::string) -> int);
};
Above, class C
will effectively become:
class C : public I
{
public:
auto STDMETHODCALLTYPE func1(int, const std::vector<int>&) -> int override;
auto STDMETHODCALLTYPE func2(std::string) -> int;
};
It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.
NOTE! MAKE_STDMETHOD_MOCK(...)
only works on Windows.
NOTE! The preprocessor is limited and can only handle nullary functions, i.e. functions that do not accept any arguments, in some cases.
-
MSVC handles nullary functions when compiling with
/Zc:preprocessor
with MSVC 19.40 (VS 17.10) or later. -
Gcc and Clang always handles nullary functions when compiling with C++20 or later, and when enabling a gcc extension by defining the macro
TROMPELOEIL_HAS_GCC_PP
before#include
:ing the trompeloeil headers, and compiling with-std=gnu++11
,-std=gnu++14
or-std=gnu++17
.
Otherwise, use MAKE_STDMETHOD_MOCK0(...)
to
explicitly define a nullary mock function.
See also MAKE_STDTMETHOD_MOCKn(...)
for explicit
function arity.
MAKE_STDMETHOD_MOCKn(
func_name, signature {, specifiers } )
Make a STDMETHODCALLTYPE mock function named func_name. It is a
good idea for this to implement a pure virtual function from an interface, but
it is not a requirement. n
is the number of parameters in signature.
specifiers is an optional list which may include attributes or specifiers like
override
or
noexcept
.
#include <trompeloeil/mock.hpp>
Example:
class I
{
public:
virtual ~I() = default;
virtual int STDMETHODCALLTYPE func1(int, const std::vector<int>&)) = 0;
};
class C : public I
{
public:
MAKE_STDMETHOD_MOCK2(func1, int(int, const std::vector<int>&), override);
MAKE_STDMETHOD_MOCK1(func2, int(std::string));
};
Above, class C
will effectively become:
class C : public I
{
public:
int STDMETHODCALLTYPE func1(int, const std::vector<int>&) override;
int STDMETHODCALLTYPE func2(std::string);
};
It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.
NOTE! MAKE_STDMETHOD_MOCKn(...)
only works on Windows.
See also MAKE_STDMETHOD_MOCK(...)
` for implicit
function arity deduction.
NAMED_ALLOW_CALL(
mock_object, func_name(parameter_list))
Make a std::unique_ptr<trompeloeil::expectation>
allowing mock_object.func_name(parameter_list) to be
called zero or more times until the expectation object is destroyed.
parameter_list may contain exact values or matchers
that describes matching calls.
This is the same as
NAMED_REQUIRE_CALL(...)
.TIMES(
0,infinity )
.
Matches any number of times, but is not required to match. (Actually the limit is 0..~0ULL, but that is for all practical purposes "infinity".)
NOTE! Any named objects referenced in attached
LR_WITH(...)
, LR_SIDE_EFFECT(...)
,
LR_RETURN(...)
and LR_THROW(...)
are
captured by reference so lifetime management is important.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
};
using trompeloeil::gt;
using trompeloeil::lt;
using expectation = std::unique_ptr<trompeloeil::expectation>;
TEST(atest)
{
C mock_obj;
expectation x1 = NAMED_ALLOW_CALL(mock_obj, func(gt(0));
test_function(0, &mock_obj);
expectation x2 = NAMED_ALLOW_CALL(mock_obj, func(lt(0));
test_function(1, &mock_obj);
x1.reset(); // no longer allow calls with positive values
test_function(2, &mock_obj);
}
Above each NAMED_ALLOW_CALL(mock_obj, func(...))
creates an expectation
that mock_obj.func() may be called any number of times. Each expectation is
valid for the lifetime of the expectation object. In the example above,
this means that x1
is valid for the first two calls to test_function(...)
,
while x2
is valid for the last two calls to test_function(...)
.
See also ALLOW_CALL(...)
which creates an expectation
that is valid until the end of the surrounding scope.
NAMED_FORBID_CALL(
mock_object, func_name(parameter_list))
Make a std::unique_ptr<trompeloeil::expectation>
disallowing calls to mock_object.func_name(parameter_list) until the
expectation object is destroyed. parameter_list may contain exact values or
matchers that describes matching calls.
This is the same as
NAMED_REQUIRE_CALL(...)
.TIMES(
0 )
, making any matching call an error. This is typically done when a wider
scope would allow the call. RETURN(...)
,
LR_RETURN(...)
, LR_THROW(...)
and
THROW(...)
are illegal in a NAMED_FORBID_CALL(...)
.
NOTE! Any named objects referenced in attached
LR_WITH(...)
are captured by reference so lifetime management
is important.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
}
using trompeloeil::_;
using trompeloeil::gt;
using trompeloeil::lt;
using expectation = std::unique_ptr<trompeloeil::expectation>;
TEST(atest)
{
C mock_obj;
ALLOW_CALL(mock_obj, func(_));
expectation x1 = NAMED_FORBID_CALL(mock_obj, func(gt(0));
test_function(0, &mock_obj);
expectation x2 = NAMED_FORBID_CALL(mock_obj, func(lt(0));
test_function(1, &mock_obj);
x1.reset(); // allow calls with positive values again
test_function(2, &mock_obj);
}
Above, calls to mock_obj.func()
are generally allowed throughout the test.
However, x1
imposes a restriction that calls with positive values are illegal,
and that restriction is in place for the first two calls to
test_function(...)
. x2
imposes a restrictions that calls with negative
values are illegal, and that restriction is in place for the last two calls to
test_function(...)
.
See also FORBID_CALL(...)
which creates an
expectation that is valid until the end of the surrounding scope.
NAMED_REQUIRE_CALL(
mock_object, func_name(parameter_list))
Make a std::unique_ptr<trompeloeil::expectation>
requiring that mock_obj.func_name(parameter_list) is called exactly once
before the expectation object is destroyed. parameter_list may contain exact
values or matchers that describes matching calls.
The number of matches required before the expectation object
is destroyed can be changed with an optional TIMES(...)
clause.
NOTE! Any named objects referenced in attached
LR_WITH(...)
, LR_SIDE_EFFECT(...)
,
LR_RETURN(...)
and LR_THROW(...)
are
captured by reference so lifetime management is important.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
}
using trompeloeil::gt;
using trompeloeil::lt;
using expectation = std::unique_ptr<trompeloeil::expectation>;
TEST(atest)
{
C mock_obj;
expectation x1 = NAMED_REQUIRE_CALL(mock_obj, func(gt(0));
test_function(0, &mock_obj);
expectation x2 = NAMED_REQUIRE_CALL(mock_obj, func(lt(0));
test_function(1, &mock_obj);
x1.reset(); // The call with positive number must be done here.
test_function(2, &mock_obj);
}
Above, the first two calls to test_function(...)
must together call
mock_obj.func(...)
exactly once with a positive value, and the last two
calls to test_function(...)
must together call mock_obj.func(...)
exactly once with a negative number.
See also REQUIRE_CALL(...)
which creates an
expectation that is valid until the end of the surrounding scope.
NAMED_REQUIRE_DESTRUCTION(
mock_object )
Create a
std::unique_ptr<trompeloeil::expectation>
object which reports a violation if the
deathwatched_type
mock object is
not destroyed by the time the expectation
is destroyed.
#include <trompeloeil/lifetime.hpp>
Example:
class C
{
public:
virtual ~C() = default; // must be virtual for deathwatched
MAKE_MOCK1(func, void(int));
}
using monitor = std::unique_ptr<trompeloeil::expectation>;
using trompeloeil::deathwatched;
TEST(atest)
{
C* p = new deathwatched<C>();
test_function(0, p); // must not destroy *p
monitor m = NAMED_REQUIRE_DESTRUCTION(*p);
test_function(1, p);
m.reset(); // *p must have been destroyed here
}
Above, p
points to a deathwatched
mock object, meaning that a violation is reported if *p
is
destroyed without having a destruction requirement.
The monitor m
is a requirement that *p
is destroyed before the
lifetime_monitor
(subtype of expectation
) held by m
is destroyed.
It is thus a violation if the first call to test_function(...)
destroys
*p
, and another violation if the second call to test_function(...)
does not destroy *p
See also REQUIRE_DESTRUCTION(...)
which places
a requirement that the deathwatched
mock object is destroyed before the end of the scope.
REQUIRE_CALL(
mock_object, func_name(parameter_list))
Make an expectation requiring that mock_obj.func_name(parameter_list) is called exactly once before the end of the scope. parameter_list may contain exact values or matchers that describes matching parameter values for the expectation.
The number of matches required before the expectation object
is destroyed can be changed with an optional TIMES(...)
clause.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(int));
}
using trompeloeil::gt;
using trompeloeil::lt;
TEST(atest)
{
C mock_obj;
{
REQUIRE_CALL(mock_obj, func(gt(0));
test_function(0, &mock_obj);
// end of scope, requirement must be fulfilled here
}
{
REQUIRE_CALL(mock_obj, func(lt(0));
test_function(1, &mock_obj);
// end of scope, requirement must be fulfilled here
}
}
Above, the first call to test_function(...)
must call
mock_obj.func(...)
exactly once with a positive value, and the second
call to test_function(...)
must call mock_obj.func(...)
exactly once with a negative number.
See also NAMED_REQUIRE_CALL(...)
which creates an
expectation that is held by a
std::unique_ptr<trompeloeil::expectation>
which can be stored in test
fixtures.
REQUIRE_DESTRUCTION(
mock_object )
Create an anonymous lifetime_monitor
which reports
a violation if the deathwatched
mock object is not destroyed by the end of the scope.
#include <trompeloeil/lifetime.hpp>
Example:
class C
{
public:
virtual ~C() = default; // must be virtual for deathwatched
MAKE_MOCK1(func, void(int));
}
using trompeloeil::deathwatched;
TEST(atest)
{
C* p = new deathwatched<C>();
test_function(0, p); // must not destroy *p
{
REQUIRE_DESTRUCTION(*p);
test_function(1, p);
// end of scope, *p must have been destroyed here
}
}
Above, p
points to a deathwatched
mock object, meaning that a violation is reported if *p
is
destroyed without having a destruction requirement.
REQUIRE_DESTRUCTION(...)
in the local scope puts a requirement on
*p
that it must be destroyed by the end of the scope.
It is thus a violation if the first call to test_function(...)
destroys
*p
, and another violation if the second call to test_function(...)
does not destroy *p
.
See also NAMED_REQUIRE_DESTRUCTION(...)
which creates the requirement that the deathwatched
mock object is destroyed as a
std::unique_ptr<trompeloeil::lifetime_monitor>
which can be stored in test fixtures.
RETURN(
expr )
Used in expectations to set the return value after having
evaluated every SIDE_EFFECT(...)
and
LR_SIDE_EFFECT(...)
.
For void
functions RETURN(...)
is illegal. For non-void
functions
exactly one of LR_RETURN(...)
, RETURN(...)
,
LR_THROW(...)
or THROW(...)
is required.
expr may refer to parameters in the call with their positional names _1
,
_2
, etc.
This code may alter out-parameters.
Named local objects accessed here refers to a immutable copies.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, int&(unsigned));
};
using trompeloeil::_;
std::vector<int> values{3,2,1,0};
TEST(atest)
{
C mock_obj;
int offset = 1;
ALLOW_CALL(mock_obj, func(_))
.WITH(_1 + offset < values.size())
.RETURN(values[_1 + offset]);
offset = 2;
test_func(&mock_obj);
}
Above, the RETURN(...)
clause tells matching calls of
mock_obj.func(...)
to return a reference to an element in the global
std::vector<int> values
. Since RETURN(...)
accesses copies of local
variables, the value of offset
is 1 in the index calculation if called from
within test_func(...)
.
NOTE! It is illegal to return a reference to a captured local variable.
See also LR_RETURN(...)
which accesses local variables
by reference.
SIDE_EFFECT(
expr )
Used in expectations to cause side effects for matching calls.
expr is only evaluated when all WITH(...)
and
LR_WITH(...)
clauses are matched. expr may refer to
parameters in the call with their positional names _1
, _2
, etc. This code
may alter out-parameters.
Several SIDE_EFFECT(...)
and LR_SIDE_EFFECT(...)
clauses can be added to a single expectation, and they are
evaluated in order.
Named local objects accessed here refers to immutable copies.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(unsigned));
};
unsigned sum = 0;
TEST(atest)
{
C mock_obj;
unsigned offset = 0;
ALLOW_CALL(mock_obj, func(ANY(unsigned))
.SIDE_EFFECT(sum += offset + _1);
offset = 2;
tested_func(&mock_obj);
std::cout << "offset corrected parameter sum=" << sum << "\n";
}
Above, tested_func(...)
is allowed to call mock_obj.func()
any
number of times. Each time a side effect is that the global
variable sum
gets the parameter value added to it adjusted for offset
.
Since SIDE_EFFECT(...)
refers to a copy of offset
, the value of
offset
is 0
in any matching calls from within tested_func(...)
See also LR_SIDE_EFFECT(...)
which accesses local
objects by reference.
THROW(
expr )
Used in expectations to throw after having evaluated every
SIDE_EFFECT(...)
and
LR_SIDE_EFFECT(...)
for a matching call.
expr may refer to parameters in the call with their positional names _1
,
_2
, etc. This code may alter out-parameters. It is not legal to combine
THROW(...)
with any of LR_THROW(...)
,
LR_RETURN(...)
or RETURN(...)
.
Named local objects here refers to immutable copies.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(unsigned));
};
TEST(atest)
{
C mock_obj;
std::string what="<unknown>";
ALLOW_CALL(mock_obj, func(3))
.THROW(std::invalid_argument(what));
what = "";
tested_func(&mock_obj);
}
Above, THROW(...)
will refer to a copy of the string what
with the value
"<unknown>"
if a matching call is made from within tested_func(...)
See also LR_THROW(...)
which accesses copies of local objects.
TIMES(
limits )
and RT_TIMES(
limits )
Used in REQUIRE_CALL(...)
and
NAMED_REQUIRE_CALL(...)
to set the limits on
the number of matching calls required.
limits may be a single number, in which case it is the exact number of matching calls required.
limits may also be two numbers, describing a range min-inclusive, max-inclusive.
If the minimum number of matching calls is not met before the end of the lifetime of the expectation, a violation is reported.
If the maximum number of matching calls is exceeded, a violation is reported.
The difference between TIMES(...)
and RT_TIMES(...)
is, that the
prior only supports constexpr
arguments, while the latter is designed to accept also runtime arguements.
If invalid bounds are provided, TIMES(...)
issues a compile-error.
RT_TIMES(...)
will compile successfully, but will raise a std::logic_error
during construction.
Either a single TIMES(...)
or RT_TIMES(...)
may be used for each
REQUIRE_CALL(..)
or
NAMED_REQUIRE_CALL(...)
.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(unsigned));
};
using trompeloeil::_;
TEST(atest)
{
C mock_obj;
REQUIRE_CALL(mock_obj, func(_))
.TIMES(2, 5);
tested_func(&mock_obj);
Above, tested_func(...)
is expected to call mock_obj.func()
at least two
times, and no more than 5 times.
See also the helpers AT_LEAST(...)
and
AT_MOST(...)
.
See also IN_SEQUENCE(...)
for information about how
.TIMES(...)
and .RT_TIMES(...)
work together with sequence
objects.
WITH(
expr )
Used with expectations to add further conditions for a
matching call. Typically used when matchers are used for the
parameters, and often when the condition requires several parameter values
together.
expr can refer to parameters in the call with their positional names _1
,
_2
, etc. Even if the function signature has parameters as non-const
references, they are immutable in this context. Several WITH(...)
and LR_WITH(...)
clauses can be added to a single expectation
and they are tried in the order until one has failed, or they all have passed.
Named local objects here refers to immutable copies.
#include <trompeloeil/mock.hpp>
Example:
class C
{
public:
MAKE_MOCK1(func, void(const char*, size_t));
};
using trompeloeil::_;
TEST(atest)
{
C mock_obj;
std::string str = "string";
REQUIRE_CALL(mock_obj, func(_,_))
.WITH(std::string(_1, _2) == str);
str = ""; // does not alter the copy in the expectation above.
tested_func(buff, &mock_obj);
}
Above, WITH(std::string(_1, _2) == str)
checks the condition that the
string constructed from the parameters is equal to a copy of the local variable
str
. To pass the test, tested_func(...)
must in other words call
mock_obj.func()
with string "string"
.
NOTE! It is legal, but a very bad idea, to modify global/static objects in
WITH(...)
. If several expectations could match and
are disambiguated by LR_WITH(...)
and WITH(...)
the
global/static objects will be modified also by those
expectations that do not match.
See also LR_WITH(...)
which accesses local objects by
reference.
Types and Templates (alphabetical order)
trompeloeil::deathwatched<T>
Template used when it is necessary to control the life time of a
mock object. The macros
REQUIRE_DESTRUCTION(...)
and
NAMED_REQUIRE_DESTRUCTION(...)
operates on instances of trompeloeil::deathwatched<T>
.
#include <trompeloeil/lifetime.hpp>
Example:
class Mock
{
public:
virtual ~Mock() = default; // virtual destructor needed for deathwatched<>
MAKE_MOCK1(func, void(int));
};
using trompeloeil::_;
void test_func()
{
auto p = new trompeloeil::deathwatched<Mock>();
ALLOW_CALL(*p, func(_));
func1(p);
{
FORBID_CALL(*p, func(_));
REQUIRE_DESTRUCTION(*p);
func2(p);
}
}
Above, func1(p)
must not destroy p
, or a violation is reported, and
func2(p)
may not call the mock function on p
, but
is required to destroy the mock object, or a violation will
be reported.
trompeloeil::deathwatched<T>
inherits from T
, and the constructor
accepts any parameters and
perfectly forwards
them to the constructor of T
. The mock type T
must have a virtual
destructor.
trompeloeil::expectation
Base class for all expectations. The macros
NAMED_ALLOW_CALL(...)
,
NAMED_FORBID_CALL(...)
and
NAMED_REQUIRE_CALL(...)
results in a
std::unique_ptr<trompeloeil::expectation>
which you can hold in a variable.
#include <trompeloeil/mock.hpp>
trompeloeil::expectation_violation
The exception type used by default to report violations.
class expectation_violation : public std::logic_error
{
public:
using std::logic_error::logic_error;
};
The what()
string contains the violation report message.
#include <trompeloeil/mock.hpp>
trompeloeil::lifetime_monitor
The macro NAMED_REQUIRE_DESTRUCTION(...)
results in a
std::unique_ptr<trompeloeil::lifetime_monitor>
which you can hold in a variable. trompeloeil::lifetime_monitor
inherits from
trompeloeil::expectation
.
#include <trompeloeil/lifetime.hpp>
Example:
class Mock
{
public:
virtual ~Mock() = default; // virtual destructor needed for deathwatched<>
MAKE_MOCK1(func, void(int));
};
using trompeloeil::_;
using monitor = std::unique_ptr<trompeloeil::lifetime_monitor>;
void test_func()
{
auto p = new trompeloeil::deathwatched<Mock>();
ALLOW_CALL(*p, func(_));
func1(p);
{
FORBID_CALL(*p, func(_));
monitor m = NAMED_REQUIRE_DESTRUCTION(*p);
std::unique_ptr<trompeloeil::expectation> e = std::move(m);
func2(p);
e.reset();
}
}
trompeloeil::matcher
trompeloeil::matcher
is the base class for all matchers. It does
not do anything and is solely used in internal
SFINAE
constructions
and tag dispatch
Use it, or trompeloeil::typed_matcher<T>
, as the base class
when writing custom matchers.
#include <trompeloeil/mock.hpp>
trompeloeil::mock_interface<T>
trompeloeil::mock_interface<T>
is a template useful when creating a mock from
an existing interface (i.e. a struct
or class
with virtual functions that
you want to mock).
It enables use of the IMPLEMENT_MOCKn(...)
and
IMPLEMENT_CONST_MOCKn(...)
macros.
The MAKE_MOCK(...)
, MAKE_MOCKn(...)
,
MAKE_CONST_MOCK(...)
and
MAKE_CONST_MOCKn(...)
macros can also be used.
The interface type T
must not be final.
#include <trompeloeil/mock.hpp>
Example:
class interface
{
public:
virtual ~interface() = default;
virtual void func(int) = 0;
};
class mock : trompeloeil::mock_interface<interface>
{
public:
IMPLEMENT_MOCK1(func); // implements pure virtual interface::func(int);
};
void tested_func(interface& i);
void test()
{
mock m;
REQUIRE_CALL(m, func(3));
tested_func(m);
}
NOTE! mock_interface<T>
cannot be used to inherit multiple interfaces.
trompeloeil::ok_reporter_func
A type used to pass information to the unit testing frame work that a call to a mock function has not been reported as a violation.
using trompeloeil::ok_reporter_func = std::function<const char*>;
#include <trompeloeil/mock.hpp>
The string passed is the parameters to the expectation. E.g.
struct Mock
{
MAKE_MOCK1(func, void(int));
};
TEST(...)
{
Mock m;
REQUIRE_CALL(m, func(3)); // passes "m.func(3)" to OK reporter
...
}
trompeloeil::printer<T>
printer<T>
is a type that formats values to strings in reports from Trompeloeil.
template <typename T, typename = void>
struct printer
{
static void print(ostream& os, const T& t);
};
By default the print
function formats using os << t
, provided the type T
can be inserted into an ostream
, otherwise it gives a hex-dump of the bytes
occupied by the object.
The type trompeloeil::printer<T>
is a customization point that you can use
to define string formatting for types that do not support os << t
, or for
which you want a different representation in reports from Trompeloeil. The
second template parameter, which must be void
if present, is a chance to add
SFINAE constraints on the T.
See example in the Cook Book.
#include <trompeloeil/mock.hpp>
trompeloeil::reporter_func
A type used to pass information to the unit testing frame work that a call has been made in violation of a mock function.
using trompeloeil::reporter_func = std::function<void(trompeloeil::severity,
char const *file,
unsigned long line,
const std::string& msg)>;
The parameter msg
contains detailed information about the violation and
which (if any) expectations there are on the
mock function.
#include <trompeloeil/mock.hpp>
trompeloeil::sequence
Type of object used for fine-tuned control of sequencing of matched expectations.
#include <trompeloeil/sequence.hpp>
Example:
class FileOps
{
public:
using handle = int;
MAKE_MOCK1(open, handle(const std::string&));
MAKE_MOCK3(write, size_t(handle, const char*, size_t));
MAKE_MOCK1(close, void(handle));
};
using trompeloeil::ne;
void test()
{
FileOps ops;
auto seq = trompeloeil::sequence; // sequence object
int handle = 4711;
REQUIRE_CALL(ops, open("name"))
.RETURN(handle)
.IN_SEQUENCE(seq);
REQUIRE_CALL(ops, write(handle, ne(nullptr), ne(0)))
.RETURN(0) // indicate failure
.IN_SEQUENCE(seq);
REQUIRE_CALL(ops, write(handle, ne(nullptr), ne(0)))
.RETURN(_3) // successful retry
.IN_SEQUENCE(seq);
REQUIRE_CALL(ops, close(handle))
.IN_SEQUENCE(seq);
test_writes(&ops);
}
Sequence objects are movable but not copyable.
NOTE! The .IN_SEQUENCE(...)
macro accepts many
sequence objects.
trompeloeil::severity
Type used in violation reports to dictate what actions are allowed by the report handler.
namespace trompeloeil {
enum class severity { fatal, nonfatal };
}
A value of trompeloeil::severity::fatal
dictates that the report handler
must not return. It may throw or end the program execution.
A value of trompeloeil::severity::nonfatal
dictates that the report handler
is called from stack rollback and must not throw, lest
std::terminate
is
called.
#include <trompeloeil/mock.hpp>
trompeloeil::stream_tracer
An instance of trompeloeil::stream_tracer
prints information about
matched calls to the
output stream
it refers to. stream_tracer
inherits from
trompeloeil::tracer
.
#include <trompeloeil/stream_tracer.hpp>
namespace trompeloeil {
class stream_tracer : public ::trompeloeil::tracer
{
public:
stream_tracer(std::ostream& stream);
void trace(char const* file, unsigned long line, std::string const& call) override;
};
}
See "Using trompeloeil::stream_tracer
" in the
Cook Book.
trompeloeil::tracer
Base class for tracers. Inherit from it when writing custom tracers.
#include <trompeloeil/stream_tracer.hpp>
namespace trompeloeil {
class tracer
{
public:
virtual void trace(char const* file, unsigned long line, std::string const& call) = 0;
protected:
tracer();
tracer(tracer const&) = delete;
virtual ~tracer();
...
};
}
See "Writing custom tracers" in the Cook Book for an example.
trompeloeil::typed_matcher<T>
Convenience class available when writing custom matchers for a specific
type. It inherits from trompeloeil::matcher
.
See "Writing custom matchers" in the Cook Book for examples.
#include <trompeloeil/matcher.hpp>
Functions
trompeloeil::expectation::is_satisfied() const
Query an expectation object if it is satisfied, i.e. if
it will not report a missing call if it is destroyed. If
.TIMES()
is used, this is true if the minimum number of calls
has been reached.
#include <trompeloeil/mock.hpp>
test(...)
{
...
auto e = NAMED_REQUIRE_CALL(mock_obj, func())
.TIMES(2,5);
assert(!e->is_satisfied()); // no calls made yet.
mock_obj.func();
assert(!e->is_satisfied()); // Only one call made, min is 2.
mock_obj.func();
assert(e->is_satisfied()); // now 2 calls are made, so it's satisfied
mock_obj.func();
assert(e->is_satisfied()); // 3 calls are made, it's still satisfied
}
trompeloeil::expectation::is_saturated() const
Query an expectation object if it is saturated, i.e. if
another call will report an unexpected call. If .TIMES()
is
used, this is true if the maximum number of calls has been reached.
#include <trompeloeil/mock.hpp>
...
auto e = NAMED_REQUIRE_CALL(mock_obj, func())
.TIMES(2,4);
assert(!e->is_saturated()); // no calls made yet.
mock_obj.func();
assert(!e->is_saturated()); // Only one call made, max is 4.
mock_obj.func();
assert(!e->is_saturated()); // now 2 calls are made, still not saturated
mock_obj.func();
assert(!e->is_saturated()); // 3 calls, one more to go.
mock_obj.func();
assert(e->is_saturated()); // 4 calls, the expectation is now saturated
/* mock_obj.func();*/ // would cause "unexpected call" error.
trompeloeil::get_lock()
Get the global
recursive_mutex
used by Trompeloeil. The mutex is held until the end of the scope.
#include <trompeloeil/mock.hpp>
trompeloeil::print(std::ostream& os, T const& t)
By default print()
uses the type printer<T>
to format
data to strings.
You can write specializations of
trompeloeil::print(std::ostream& os, T const& t)
for your own types
T
, but it is preferable to write a specialization of the type
printer<T>
instead, which also works for partial
specializations. See example in the
Cook Book.
#include <trompeloeil/mock.hpp>
trompeloeil::is_null(T const&)
Null check that works for all types. If T
is not comparable with
nullptr
the value is false. This is mostly used when writing
duck typed matchers.
#include <trompeloeil/mock.hpp>
trompeloeil::make_matcher<Type>(...)
template <typename Type, typename Predicate, typename Printer, typename ... T>
auto make_matcher(Predicate predicate /* bool (Type& value, T const& ...) */,
Printer printer /* void (std::ostream&, T const& ...) */,
T&& ... stored_values);
If Type
is trompeloeil::wildcard
a
duck typed matcher is created, otherwise
a matcher for the specified type Type
is created.
T&&...
is any number of values you want stored in the matcher.
predicate
is a callable object, typically a lambda, that accepts the
value to check for, and each of the stored values T&&...
in order as
const&
. When Type
is trompeloeil::wildcard
, the first parameter must
be of auto
type. The return value must be convertible to bool
.
printer
is a callable object, typically a lambda, that accepts an
ostream&
and the
stored values T&&...
in order as const&
.
Examples are found in the Cook Book under Writing custom matchers
#include <trompeloeil/matcher.hpp>
trompeloeil::set_reporter(...)
These functions are used to adapt Trompeloeil to your unit test framework of choice.
The default reporter throws
trompeloeil::expectation_violation
for
all reports, with the violation message in the what()
string.
If this is not suitable, you can change the report mechanism by
calling trompeloeil::set_reporter(...)
#include <trompeloeil/mock.hpp>
reporter_func
trompeloeil::set_reporter(std::function<void(trompeloeil::severity,
char const *file,
unsigned long line,
const std::string& msg)>)
The return value is the previous reporter function.
std::pair<reporter_func, ok_reporter_func>
trompeloeil::set_reporter(std::function<void(trompeloeil::severity,
char const *file,
unsigned long line,
const std::string& msg)> reporter,
std::function<void(char const* msg> ok_reporter)
)
The return value is the previous reporter
and ok_reporter
. An ok_reporter
is called for every call to a mock function that is not
reported as a violation. By default OK reports are ignored.
See trompeloeil::severity
for the rules that it
dictates.
See trompeloeil::reporter_func
and
trompeloeil::ok_reporter_func
for details.
The Cook Book lists adapter code for a number of popular unit test frame works.
bool trompeloeil::sequence::is_completed() const
Member function of sequence
object, used to query if
the sequence it describes is completed or not.
#include <trompeloeil/sequence.hpp>
Example:
void test()
{
auto seq = trompeloeil::sequence;
mock_type mock;
REQUIRE_CALL(mock, func1())
.IN_SEQUENCE(seq);
REQUIRE_CALL(mock, func2())
.TIMES(100)
.IN_SEQUENCE(seq);
assert(!seq.is_completed()); // no calls yet
mock.func1();
assert(!seq.is_completed()); // only first call, one remaining
mock.func2();
assert(seq.is_completed()); // now sequence is completed
}
Constants
trompeloeil_movable_mock
By adding a static constexpr bool member trompeloeil_movable_mock
with the
value true
to your mock struct/class, you make it move constructible. Note
that when a mock object is moved, any current expectations will be taken over
by the newly constructed mock object, but note also that if the implicitly
created lambdas associated with
.WITH()
,
.SIDE_EFFECT()
,
.RETURN()
and
.THROW()
and their LR_
counter parts, refers
to member variables in the mock objects, they will continue to refer the old
moved from object.
#include <trompeloeil/mock.hpp>
class immobile
{
public:
MAKE_MOCK1(func, void(int));
};
class movable
{
public:
int i = 0;
static constexpr bool trompeloeil_movable_mock = true;
// allow move construction
MAKE_MOCK1(func, void(int));
};
template <typename T>
T transfer(T t)
{
return t;
}
test(...)
{
auto m = transfer(immobile{}); // compilation error
...
}
test(...)
{
movable m;
auto e = NAMED_REQUIRE_CALL(m, func(3));
auto mm = transfer(std::move(m));
// A call to mm.func() now satisfies e
...
}
test(...)
{
movable m{3};
auto e = NAMED_REQUIRE_CALL(m, func(_))
.LR_WITH(_1 == m.i);
auto mm = transfer(std::move(m)); // Danger! e still refers to m.i.
...
}
Also, keep in mind the lifetime of expectations. If the lifetime of an expectation is associated with the life of the moved-from object, your test will likely fail, since the expectation object would then be destroyed before it has been satisfied. Example:
class movable
{
public:
static constexpr bool trompeloeil_movable_mock = true;
MAKE_MOCK0(func, void());
};
movable setup()
{
movable obj;
REQUIRE_CALL(obj, func());
return obj;
// Expectation dies here, unsatisfied, failing the test
}
test(...)
{
movable obj = setup(); // test fails when returning from setup()
...
}
Using
NAMED_REQUIRE_CALL()
,
NAMED_ALLOW_CALL()
or
NAMED_FORBID_CALL()
can help, since
they make the expectation life times more visible.