mirror of https://github.com/rollbear/trompeloeil
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3788 lines
109 KiB
Markdown
3788 lines
109 KiB
Markdown
# Reference
|
|
|
|
<!-- no toc -->
|
|
- [Notions](#notions)
|
|
- [Mock function](#mock_function)
|
|
- [Mock object](#mock_object)
|
|
- [Expectation](#expectation)
|
|
- [Matcher](#matcher)
|
|
- [_](#wildcard)
|
|
- [**`ANY(`** *type* **`)`**](#ANY)
|
|
- [**`MEMBER_IS(`** *member*, *matcher* **`)`**](#MEMBER_IS)
|
|
- [**`all_of(`** *values* **`)`**](#all_of)
|
|
- [**`any_of(`** *values* **`)`**](#any_of)
|
|
- [**`eq(`** *value* **`)`**](#eq)
|
|
- [**`ne(`** *value* **`)`**](#ne)
|
|
- [**`gt(`** *value* **`)`**](#gt)
|
|
- [**`ge(`** *value* **`)`**](#ge)
|
|
- [**`lt(`** *value* **`)`**](#lt)
|
|
- [**`le(`** *value* **`)`**](#le)
|
|
- [**`none_of(`** *values* **`)`**](#none_of)
|
|
- [**`re(`** *string* **`)`**](#re)
|
|
- [**`range_includes(`** *values **`)`**](#range_includes)
|
|
- [**`range_is(`** *values* **`)`**](#range_is)
|
|
- [**`range_all_of(`** *matcher* **`)`**](#range_all_of)
|
|
- [**`range_any_of(`** *matcher* **`)`**](#range_any_of)
|
|
- [**`range_none_of(`** *matcher* **`)`**](#range_none_of)
|
|
- [**`range_is_permutation(`** *values* **`)`**](#range_is_permutation)
|
|
- [**`range_starts_with(`** *values* **`)`**](#range_starts_with)
|
|
- [**`range_ends_with(`** *values* **`)`**](#range_ends_with)
|
|
- [**`*`** *matcher*](#deref_matcher)
|
|
- [**`!`** *matcher*](#not_matcher)
|
|
- [Macros](#macros) (alphabetical order)
|
|
- [**`ALLOW_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#ALLOW_CALL)
|
|
- [**`ANY(`** *type* **`)`**](#ANY_MACRO)
|
|
- [**`AT_LEAST(`** *number* **`)`**](#AT_LEAST)
|
|
- [**`AT_MOST(`** *number* **`)`**](#AT_MOST)
|
|
- [**`CO_RETURN(`** *expr **`)**](#CO_RETURN)
|
|
- [**`CO_THROW(`** *expr **`)**](#CO_THROW)
|
|
- [**`CO_YIELD(`** *expr **`)**](#CO_YIELD)
|
|
- [**`FORBID_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#FORBID_CALL)
|
|
- [**`IMPLEMENT_CONST_MOCKn(`** *func_name* **`)`**`](#IMPLEMENT_CONST_MOCKn)
|
|
- [**`IMPLEMENT_MOCKn(`** *func_name* **`)`**`](#IMPLEMENT_MOCKn)
|
|
- [**`IMPLEMENT_STDMETHOD_MOCKn(`** *func_name* **`)`**`](#IMPLEMENT_STDMETHOD_MOCKn)
|
|
- [**`IN_SEQUENCE(`** *seq...* **`)`**](#IN_SEQUENCE)
|
|
- [**`LR_CO_RETURN(`** *expr* **`)`**](#LR_CO_RETURN)
|
|
- [**`LR_CO_THROW(`** *expr* **`)`**](#LR_CO_THROW)
|
|
- [**`LR_CO_YIELD(`** *expr* **`)`**](#LR_CO_YIELD)
|
|
- [**`LR_RETURN(`** *expr* **`)`**](#LR_RETURN)
|
|
- [**`LR_SIDE_EFFECT(`** *expr* **`)`**](#LR_SIDE_EFFECT)
|
|
- [**`LR_THROW(`** *expr* **`)`**](#LR_THROW)
|
|
- [**`LR_WITH(`** *expr* **`)`**](#LR_WITH)
|
|
- [**`MAKE_CONST_MOCK(`** *func_name*, *signature* **`)`**](#MAKE_CONST_MOCK)
|
|
- [**`MAKE_CONST_MOCKn(`** *func_name*, *signature* **`)`**](#MAKE_CONST_MOCKn)
|
|
- [**`MAKE_MOCK(`** *name*, *signature* **`)`**](#MAKE_MOCK)
|
|
- [**`MAKE_MOCKn(`** *name*, *signature* **`)`**](#MAKE_MOCKn)
|
|
- [**`MAKE_STDMETHOD_MOCK(`** *name*, *signature* **`)`**](#MAKE_STDMETHOD_MOCK)
|
|
- [**`MAKE_STDMETHOD_MOCKn(`** *name*, *signature* **`)`**](#MAKE_STDMETHOD_MOCKn)
|
|
- [**`NAMED_ALLOW_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#NAMED_ALLOW_CALL)
|
|
- [**`NAMED_FORBID_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#NAMED_FORBID_CALL)
|
|
- [**`NAMED_REQUIRE_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#NAMED_REQUIRE_CALL)
|
|
- [**`NAMED_REQUIRE_DESTRUCTION(`** *mock_object* **`)`**](#NAMED_REQUIRE_DESTRUCTION)
|
|
- [**`REQUIRE_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#REQUIRE_CALL)
|
|
- [**`REQUIRE_DESTRUCTION(`** *mock_object* **`)`**](#REQUIRE_DESTRUCTION)
|
|
- [**`RETURN(`** *expr* **`)`**](#RETURN)
|
|
- [**`RT_TIMES(`** *limit* **`)`**](#TIMES-and-RT_TIMES)
|
|
- [**`SIDE_EFFECT(`** *expr* **`)`**](#SIDE_EFFECT)
|
|
- [**`THROW(`** *expr* **`)`**](#THROW)
|
|
- [**`TIMES(`** *limit* **`)`**](#TIMES-and-RT_TIMES)
|
|
- [**`WITH(`** *expr* **`)`**](#WITH)
|
|
- [Types and Type Templates](#types_and_templates) (alphabetical order)
|
|
- [`trompeloeil::deathwatched<T>`](#deathwatched_type)
|
|
- [`trompeloeil::expectation`](#expectation_type)
|
|
- [`trompeloeil::expectation_violation`](#expectation_violation_type)
|
|
- [`trompeloeil::lifetime_monitor`](#lifetime_monitor_type)
|
|
- [`trompeloeil::matcher`](#matcher_type)
|
|
- [`trompeloeil::mock_interface<T>`](#mock_interface)
|
|
- [`trompeloeil::ok_reporter_func`](#ok_reporter_func)
|
|
- [`trompeloeil::printer`](#printer)
|
|
- [`trompeloeil::reporter_func`](#reporter_func)
|
|
- [`trompeloeil::sequence`](#sequence_type)
|
|
- [`trompeloeil::severity`](#severity_type)
|
|
- [`trompeloeil::stream_tracer`](#stream_tracer)
|
|
- [`trompeloeil::tracer`](#tracer_type)
|
|
- [`trompeloeil::typed_matcher<T>`](#typed_matcher)
|
|
- [Functions and Function Templates](#functions)
|
|
- [`trompeloeil::expectation::is_satisfied()`](#is_satisfied)
|
|
- [`trompeloeil::expectation::is_saturated()`](#is_saturated)
|
|
- [`trompeloeil::get_lock()`](#get_lock)
|
|
- [`trompeloeil::print(std::ostream&, T const&)`](#print)
|
|
- [`trompeloeil::is_null(T const &)`](#is_null)
|
|
- [`trompeloeil::make_matcher<Type>(...)`](#make_matcher)
|
|
- [`trompeloeil::set_reporter(...)`](#set_reporter)
|
|
- [`trompeloeil::sequence::is_completed()`](#is_completed)
|
|
- [Constants](#constants)
|
|
- [`trompeloeil_movable_mock`](#movable_mock)
|
|
|
|
## <A name="notions"/>Notions
|
|
|
|
### <A name="mock_function"/>Mock function
|
|
|
|
A *mock function* is a member function that is mocked with
|
|
[**`MAKE_MOCK(name, signature)`**](#MAKE_MOCK),
|
|
[**`MAKE_MOCKn(name, signature)`**](#MAKE_MOCKn),
|
|
[**`MAKE_CONST_MOCK(name, signature)`**](#MAKE_CONST_MOCK) or
|
|
[**`MAKE_CONST_MOCKn(name, signature)`**](#MAKE_CONST_MOCKn).
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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](#mock_object)
|
|
of type `C` it is possible to place [expectations](#expectation)
|
|
on the functions `func(...)` and `cfunc(...)`.
|
|
|
|
### <A name="mock_object"/>Mock object
|
|
|
|
A *mock object* is an object of a type that has [mock functions](#mock_function).
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
class C
|
|
{
|
|
public:
|
|
MAKE_MOCK1(func, void(int));
|
|
};
|
|
|
|
C obj;
|
|
```
|
|
|
|
Above, `obj` is a mock object. It is possible to place
|
|
[expectations](#expectation) on [mock functions](#mock_function) for the object
|
|
`obj`.
|
|
|
|
### <A name="expectation"/>Expectation
|
|
|
|
By default it is illegal to call [mock functions](#mock_function). Expectations
|
|
change that. Example:
|
|
|
|
```Cpp
|
|
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](#mock_object) with one
|
|
[mock function](#mock_function) `void func(int)`.
|
|
|
|
The line [*`REQUIRE_CALL(mock_obj, func(3))`*](#REQUIRE_CALL) 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*)**`)`**](#REQUIRE_CALL)
|
|
- [**`ALLOW_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#ALLOW_CALL)
|
|
- [**`FORBID_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#FORBID_CALL)
|
|
- [**`NAMED_REQUIRE_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#NAMED_REQUIRE_CALL)
|
|
- [**`NAMED_ALLOW_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#NAMED_ALLOW_CALL)
|
|
- [**`NAMED_FORBID_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**](#NAMED_FORBID_CALL)
|
|
|
|
Each **NAMED** variant returns an expectation as
|
|
[`std::unique_ptr<trompeloeil::expectation>`](#expectation_type) 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(...)`**](#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:
|
|
|
|
```Cpp
|
|
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(...)`**](#ALLOW_CALL) matches
|
|
everything using the wildcard [`trompeloeil::_`](#wildcard), but the two
|
|
[**`FORBID_CALL(...)`**](#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(...)`**](#FORBID_CALL) do not match, but the
|
|
[**`ALLOW_CALL(...)`**](#ALLOW_CALL) does, so the call is allowed. A call with
|
|
`3` or `4`, results in a violation is report since a
|
|
[**`FORBID_CALL(...)`**](#FORBID_CALL) is matched.
|
|
|
|
### <A name="matcher"/>Matcher
|
|
|
|
Each parameter in the parameter list of an [expectation](#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
|
|
|
|
- [_](#wildcard)
|
|
- [**`ANY(`** *type* **`)`**](#ANY)
|
|
- [**`MEMBER_IS(`** *member*, *matcher* **`)`**](#MEMBER_IS)
|
|
- [**`all_of(`** *values* **`)`**](#all_of)
|
|
- [**`any_of(`** *values* **`)`**](#any_of)
|
|
- [**`eq(`** *value* **`)`**](#eq)
|
|
- [**`ne(`** *value* **`)`**](#ne)
|
|
- [**`gt(`** *value* **`)`**](#gt)
|
|
- [**`ge(`** *value* **`)`**](#ge)
|
|
- [**`lt(`** *value* **`)`**](#lt)
|
|
- [**`le(`** *value* **`)`**](#le)
|
|
- [**`none_of(`** *values* **`)`**](#none_of)
|
|
- [**`re(`** *string* **`)`**](#re)
|
|
- [**`range_includes(`** *values* **`)`**](#range_includes)
|
|
- [**`range_is(`** *values* **`)`**](#range_is)
|
|
- [**`range_all_of(`** *matcher* **`)`**](#range_all_of)
|
|
- [**`range_any_of(`** *matcher* **`)`**](#range_any_of)
|
|
- [**`range_none_of(`** *matcher* **`)`**](#range_none_of)
|
|
- [**`range_is_permutation(`** *values* **`)`**](#range_is_permutation)
|
|
- [**`range_starts_with(`** *values* **`)`**](#range_starts_with)
|
|
- [**`range_ends_with(`** *values* **`)`**](#range_ends_with)
|
|
|
|
|
|
You can also provide [your own matchers](CookBook.md/#custom_matchers).
|
|
|
|
#### <A name="wildcard"/>**`_`**
|
|
|
|
Used in the parameter list of an [expectation](#expectation), `trompeloeil::_`
|
|
matches any value of any type.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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* **`)`**](#ANY).
|
|
|
|
#### <A name="MEMBER_IS"/>**`MEMBER_IS(`** *member*, *matcher* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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* **`)`**](#gt). This es especially useful together with the
|
|
matchers [**`all_of(`** *values* **`)`**](#all_of) and
|
|
[**`any_of(`** *values* **`)`**](#any_of)
|
|
|
|
`#include <trompeloeil/matcher/member_is.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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`.
|
|
|
|
|
|
#### <A name="ANY"/>**`ANY(`** *type* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#expectation) to match any value
|
|
of a specified type. This can be used as an alternative to
|
|
[`trompeloeil::_`](#wildcard) when it is important to disambiguate between
|
|
overloads.
|
|
|
|
`#include <trompeloeil/matcher/any.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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](#expectation).
|
|
|
|
#### <A name="all_of"/>**`all_of(`** *values* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#expectation) matches only calls to
|
|
`mock_obj.func(const char*)`, with a C-string `"foo"`.
|
|
|
|
|
|
#### <A name="any_of"/>**`any_of(`** *values* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#expectation) matches only calls to
|
|
`mock_obj.func(const char*)`, with either `nullptr` or a C-string `"foo"`.
|
|
|
|
|
|
#### <A name="eq"/>**`eq(`** *value* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#expectation) matches only calls to
|
|
`mock_obj.func(const char*)`, with a C-string `"foo"`.
|
|
|
|
#### <A name="ne"/>**`ne(`** *value* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#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.
|
|
|
|
#### <A name="gt"/>**`gt(`** *value* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#expectation) matches calls to
|
|
`mock_obj.func(std::string)`, since
|
|
[`std::string`](http://en.cppreference.com/w/cpp/string/basic_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.
|
|
|
|
#### <A name="ge"/>**`ge(`** *value* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#expectation) matches only calls to
|
|
`mock_obj.func(std::string)`, since
|
|
[`std::string`](http://en.cppreference.com/w/cpp/string/basic_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.
|
|
|
|
#### <A name="lt"/>**`lt(`** *value* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#expectation) matches calls to
|
|
`mock_obj.func(cost std::string&)`, since
|
|
[`std::string`](http://en.cppreference.com/w/cpp/string/basic_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.
|
|
|
|
#### <A name="le"/>**`le(`** *value* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#expectation) matches calls to
|
|
`mock_obj.func(const char*)`, since a c-string is less-than comparable
|
|
with a [`std::string`](http://en.cppreference.com/w/cpp/string/basic_string)
|
|
|
|
It is also possible to use `*le(val)` to match a pointer to a less-than or
|
|
equal value.
|
|
|
|
|
|
#### <A name="none_of"/>**`none_of(`** *values* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#expectation) matches only calls to
|
|
`mock_obj.func(const char*)`, with a non-null pointer, pointing to a C-string
|
|
that is not `"foo"`.
|
|
|
|
|
|
|
|
#### <A name="re"/>**`re(`** *string* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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 as
|
|
`C++` `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()`](http://en.cppreference.com/w/cpp/regex/regex_search)
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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.
|
|
|
|
|
|
#### <A name="range_includes"/>**`range_includes(`** matchers **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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 like [**`re(`** *string* **`)`**](#re)
|
|
* **`range_includes(`** *values* **`)`** where values is a collection, e.g. a [`std::vector<>`](https://en.cppreference.com/w/cpp/container/vector) or C-array, of values.
|
|
|
|
Example using matchers:
|
|
|
|
```Cpp
|
|
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](#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](#expectation)
|
|
matches.
|
|
|
|
The second [expectation](#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:
|
|
|
|
```Cpp
|
|
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.
|
|
|
|
#### <A name="range_is"/>**`range_is(`** *matchers* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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 like [**`re(`** *string* **`)`**](#re)
|
|
* **`range_is(`** *values* **`)`** where values is a collection, e.g. a [`std::vector<>`](https://en.cppreference.com/w/cpp/container/vector) or C-array, of values.
|
|
|
|
Example using matchers:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#expectation) matches calls to
|
|
`mock_obj.ofunc(const std::list<int>&)` with the values `{ 1, 2, 3 }`.
|
|
|
|
Example using C-array of values:
|
|
|
|
```Cpp
|
|
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 }.
|
|
|
|
#### <A name="range_all_of"/>**`range_all_of(`** *matcher* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#expectation) matches calls to
|
|
`mock_obj.ofunc(const std::list<int>&)` with values `> 0`.
|
|
|
|
The matcher `range_all_of` always matches an empty range.
|
|
|
|
|
|
#### <A name="range_any_of"/>**`range_any_of(`** *matcher* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#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.
|
|
|
|
#### <A name="range_none_of"/>**`range_none_of(`** *matcher* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#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.
|
|
|
|
|
|
#### <A name="range_is_permutation"/>**`range_is_permutation(`** *matchers* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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 like [**`re(`** *string* **`)`**](#re)
|
|
* **`range_is_permutation(`** *values* **`)`** where values is a collection, e.g. a [`std::vector<>`](https://en.cppreference.com/w/cpp/container/vector) or C-array, of values.
|
|
|
|
Example using matchers:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#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* **`)`**](#gt). 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:
|
|
|
|
```Cpp
|
|
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.
|
|
|
|
#### <A name="range_starts_with"/>**`range_starts_with(`** *matchers* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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 like [**`re(`** *string* **`)`**](#re)
|
|
* **`range_starts_with(`** *values* **`)`** where values is a collection, e.g. a [`std::vector<>`](https://en.cppreference.com/w/cpp/container/vector) or C-array, of values.
|
|
|
|
Example using matchers:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#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:
|
|
|
|
```Cpp
|
|
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}.
|
|
|
|
#### <A name="range_ends_with"/>**`range_ends_with(`** *matchers* **`)`**
|
|
|
|
Used in the parameter list of an [expectation](#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 like [**`re(`** *string* **`)`**](#re)
|
|
* **`range_ends_with(`** *values* **`)`** where values is a collection, e.g. a [`std::vector<>`](https://en.cppreference.com/w/cpp/container/vector) or C-array, of values.
|
|
|
|
Example using matchers:
|
|
|
|
```Cpp
|
|
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](#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](#expectation) matches.
|
|
|
|
The second [expectation](#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:
|
|
|
|
```Cpp
|
|
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.
|
|
|
|
#### <A name="deref_matcher"/>**`*`** *matcher*
|
|
|
|
Used in the parameter list of an [expectation](#expectation) together with a
|
|
matcher, to match a value pointed to by a pointer. A
|
|
[`nullptr`](http://en.cppreference.com/w/cpp/language/nullptr) value fails the
|
|
matcher.
|
|
|
|
`#include <trompeloeil/matcher/deref.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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`.
|
|
|
|
#### <A name="not_matcher"/>**`!`** *matcher*
|
|
|
|
Used in the parameter list of an [expectation](#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:
|
|
|
|
```Cpp
|
|
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"`.
|
|
|
|
## <A name="macros"/>Macros
|
|
|
|
<A name="ALLOW_CALL"/>
|
|
|
|
### **`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](#matcher)
|
|
that describes matching calls.
|
|
|
|
This is the same as
|
|
[**`REQUIRE_CALL(...)`**](#REQUIRE_CALL).[**`TIMES(`**](#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:
|
|
|
|
```Cpp
|
|
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(...)`**](#NAMED_ALLOW_CALL) which creates an
|
|
expectation as a
|
|
[`std::unique_ptr<trompeloeil::expectation>`](#expectation_type) which can be
|
|
stored in test fixtures or otherwise have its lifetime programmatically controlled.
|
|
|
|
<A name="ANY_MACRO"/>
|
|
|
|
### **`ANY(`** *type* **`)`**
|
|
|
|
A [matcher](#matcher) for use in the parameter list of an
|
|
[expectation](#expectation) to disambiguate overloaded functions on type when
|
|
the exact value is unimportant. See the matcher [**`ANY(`** *type* **`)`**](#ANY) above.
|
|
|
|
`#include <trompeloeil/matcher/any.hpp>`
|
|
|
|
<A name="AT_LEAST"/>
|
|
|
|
### **`AT_LEAST(`** *number* **`)`**
|
|
|
|
Used in [**`TIMES(...)`**](#TIMES) to set the range *number*..infinity.
|
|
*number* must be
|
|
[`constexpr`](http://en.cppreference.com/w/cpp/language/constexpr).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(`**](#TIMES)**`AT_LEAST(3))`** modifies the
|
|
[expectation](#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"_.
|
|
|
|
<A name="AT_MOST"/>
|
|
|
|
### **`AT_MOST(`** *number* **`)`**
|
|
|
|
Used in [**`TIMES(...)`**](#TIMES) to set the range 0..*number*.
|
|
*number* must be
|
|
[`constexpr`](http://en.cppreference.com/w/cpp/language/constexpr).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(`**](#TIMES)**`AT_MOST(3))`** modifies the
|
|
[expectation](#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.
|
|
|
|
<A name="CO_RETURN"/>
|
|
|
|
### **`CO_RETURN(`** *expr* **`)`**
|
|
|
|
Used in [expectations](#expectation) to set the return value from a coroutine.
|
|
Note that when [**`SIDE_EFFECT(...)`**](#SIDE_EFFECT) and
|
|
[**`LR_SIDE_EFFECT(...)`**](#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`**](https://eel.is/c++draft/cpp.predefined#:__cpp_impl_coroutine)
|
|
feature test macro.
|
|
|
|
|
|
**NOTE!** Be very extra careful with lifetime issues when dealing with coroutines.
|
|
|
|
<A name="CO_THROW"/>
|
|
|
|
### **`CO_THROW(`** *expr* **`)`**
|
|
|
|
Used in [expectations](#expectation) to throw an exception from a coroutine.
|
|
Note that when any [**`SIDE_EFFECT(...)`**](#SIDE_EFFECT) and
|
|
[**`LR_SIDE_EFFECT(...)`**](#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`**](https://eel.is/c++draft/cpp.predefined#:__cpp_impl_coroutine)
|
|
feature test macro.
|
|
|
|
**NOTE!** Be very extra careful with lifetime issues when dealing with coroutines.
|
|
|
|
<A name="CO_YIELD"/>
|
|
|
|
### **`CO_YIELD(`** *expr* **`)`**
|
|
|
|
Used in [expectations](#expectation) with a coroutine type that can
|
|
[`co_yield`](https://en.cppreference.com/w/cpp/language/coroutines#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* **`)`**](#CO_RETURN) or
|
|
[**`LR_CO_RETURN(`** *expr* **`)`**](#LR_CO_RETURN) is still needed.
|
|
|
|
See also [**`LR_CO_YIELD(`** *expr* **`]`**](#LR_CO_YIELD)
|
|
|
|
`#include <trompeloeil/coro.hpp>`
|
|
|
|
Coroutines are supported if the compiler defines the
|
|
[**`__cpp_impl_coroutines`**](https://eel.is/c++draft/cpp.predefined#:__cpp_impl_coroutine)
|
|
feature test macro.
|
|
|
|
**NOTE!** Be very extra careful with lifetime issues when dealing with coroutines.
|
|
|
|
<A name="FORBID_CALL"/>
|
|
|
|
### **`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](#matcher) that describes matching calls.
|
|
|
|
This is the same as
|
|
[**`REQUIRE_CALL(...)`**](#REQUIRE_CALL).[**`TIMES(`**](#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(...)`**](#LR_RETURN),
|
|
[**`RETURN(...)`**](#RETURN), [**`LR_THROW(...)`**](#LR_THROW) and
|
|
[**`THROW(...)`**](#THROW) are illegal in a **`FORBID_CALL(...)`**.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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](#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(...)`**](#NAMED_FORBID_CALL) which creates an
|
|
expectation as a
|
|
[`std::unique_ptr<trompeloeil::expectation>`](#expectation_type) which can be
|
|
stored in test fixtures or otherwise have its lifetime programmatically controlled.
|
|
|
|
<A name="IMPLEMENT_CONST_MOCKn"/>
|
|
|
|
### **`IMPLEMENT_CONST_MOCKn(`** *func_name* {, *specifiers* } **`)`**
|
|
|
|
Make a `const` [mock function](#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>`](#mock_interface), where `T` is the interface.
|
|
|
|
*specifiers* is an optional list which may include attributes or specifiers like
|
|
[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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:
|
|
|
|
```Cpp
|
|
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](#mock_function) from those.
|
|
|
|
**NOTE!** **`IMPLEMENT_CONST_MOCKn(...)`** cannot handle overloaded functions.
|
|
|
|
See also [**`IMPLEMENT_MOCKn(...)`**](#IMPLEMENT_MOCKn) for non-`const`
|
|
member functions.
|
|
|
|
See also [**`MAKE_MOCK(...)`**](#MAKE_MOCK),
|
|
[**`MAKE_MOCKn(...)`**](#MAKE_MOCKn),
|
|
[**`MAKE_CONST_MOCK(...)`**](#MAKE_CONST_MOCK) and
|
|
[**`MAKE_CONST_MOCKn(...)`**](#MAKE_CONST_MOCKn) for making mock implementations
|
|
of any member functions.
|
|
|
|
<A name="IMPLEMENT_MOCKn"/>
|
|
|
|
### **`IMPLEMENT_MOCKn(`** *func_name* {, *specifiers* } **`)`**
|
|
|
|
Make a non-`const` [mock function](#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>`](#mock_interface), where `T` is the interface.
|
|
|
|
*specifiers* is an optional list which may include attributes or specifiers like
|
|
[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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:
|
|
|
|
```Cpp
|
|
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](#mock_function) from those.
|
|
|
|
**NOTE!** **`IMPLEMENT_MOCKn(...)`** cannot handle overloaded functions.
|
|
|
|
See also [**`IMPLEMENT_CONST_MOCKn(...)`**](#IMPLEMENT_CONST_MOCKn) for `const`
|
|
member functions.
|
|
|
|
See also [**`MAKE_CONST_MOCKn(...)`**](#MAKE_CONST_MOCKn) for `const`
|
|
member functions.
|
|
|
|
<A name="IMPLEMENT_STDMETHOD_MOCKn"/>
|
|
|
|
### **`IMPLEMENT_STDMETHOD_MOCKn(`** *func_name* {, *specifiers* } **`)`**
|
|
|
|
Make a `STDMETHODCALLTYPE` [mock function](#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>`](#mock_interface), where `T` is the interface.
|
|
|
|
*specifiers* is an optional list which may include attributes or specifiers like
|
|
[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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:
|
|
|
|
```Cpp
|
|
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](#mock_function) from those.
|
|
|
|
**NOTE!** **`IMPLEMENT_STDMETHOD_MOCKn(...)`** cannot handle overloaded functions.
|
|
|
|
**NOTE!** **`IMPLEMENT_STDMETHOD_MOCKn(...)`** only works on Windows.
|
|
|
|
See also [**`MAKE_STDMETHOD_MOCKn(...)`**](#MAKE_STDMETHOD_MOCKn)
|
|
|
|
<A name="IN_SEQUENCE"/>
|
|
|
|
### **`IN_SEQUENCE(`** *seq...* **`)`**
|
|
|
|
Where *seq...* is one or more instances of `trompeloeil::sequence`. Impose an
|
|
order in which [expectations](#expectation) and destruction of
|
|
[**`deathwatched_type`**](#deathwatched_type) objects must match.
|
|
Several sequences can be parallel and interleaved. A sequence for an
|
|
[expectation](#expectation) can move forward to the next once the lower
|
|
limit from [**`TIMES(...)`**](#TIMES) is reached (defaults to 1). This means
|
|
that if the lower limit is 0 (see [**`ALLOW_CALL(...)`**](#ALLOW_CALL)), the
|
|
expectation may be skipped in the sequence.
|
|
|
|
`#include <trompeloeil/sequence.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(...)`**](#REQUIRE_CALL),
|
|
thus it must be the first [expectation](#expectation) matched. Likewise all
|
|
sequences are listed in the last
|
|
[**`REQUIRE_CALL(...)`**](#REQUIRE_CALL), so it must be last
|
|
[expectation](#expectation) matched. The intermediate
|
|
[expectations](#expectation) has one sequence object each, thus they have no
|
|
matching order imposed between them. Last of all is the
|
|
[**`REQUIRE_DESTRUCTION(...)`**](#REQUIRE_DESTRUCTION), which also lists
|
|
all sequence objects and must happen after all other
|
|
[expectations](#expectation) 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(...)`**](#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(...)`**](#TIMES) is reached, or a different expectation matches.
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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`.
|
|
|
|
<A name="LR_CO_RETURN"/>
|
|
|
|
### **`LR_CO_RETURN(`** *expr* **`)`**
|
|
|
|
Used in [expectations](#expectation) to set the return value from a coroutine.
|
|
Note that when any [**`SIDE_EFFECT(...)`**](#SIDE_EFFECT) and
|
|
[**`LR_SIDE_EFFECT(...)`**](#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`**](https://eel.is/c++draft/cpp.predefined#:__cpp_impl_coroutine)
|
|
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.
|
|
|
|
<A name="LR_CO_THROW"/>
|
|
|
|
### **`LR_CO_THROW(`** *expr* **`)`**
|
|
|
|
Used in [expectations](#expectation) to throw an exception from a coroutine.
|
|
Note that when any [**`SIDE_EFFECT(...)`**](#SIDE_EFFECT) and
|
|
[**`LR_SIDE_EFFECT(...)`**](#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`**](https://eel.is/c++draft/cpp.predefined#:__cpp_impl_coroutine)
|
|
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.
|
|
|
|
<A name="LR_CO_YIELD"/>
|
|
|
|
### **`LR_CO_YIELD(`** *expr* **`)`**
|
|
|
|
Used in [expectations](#expectation) with a coroutine type that can
|
|
[`co_yield`](https://en.cppreference.com/w/cpp/language/coroutines#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* **`)`**](#CO_RETURN) or
|
|
[**`LR_CO_RETURN(`** *expr* **`)`**](#LR_CO_RETURN) is still needed.
|
|
|
|
See also [**`CO_YIELD(`** *expr* **`]`**](#LR_CO_YIELD)
|
|
|
|
`#include <trompeloeil/coro.hpp>`
|
|
|
|
Coroutines are supported if the compiler defines the
|
|
[**`__cpp_impl_coroutines`**](https://eel.is/c++draft/cpp.predefined#:__cpp_impl_coroutine)
|
|
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.
|
|
|
|
<A name="LR_RETURN"/>
|
|
|
|
### **`LR_RETURN(`** *expr* **`)`**
|
|
|
|
Used in [expectations](#expectation) to set the return value after having
|
|
evaluated every [**`SIDE_EFFECT(...)`**](#SIDE_EFFECT) and
|
|
[**`LR_SIDE_EFFECT(...)`**](#LR_SIDE_EFFECT).
|
|
For `void` functions **`LR_RETURN(...)`** is illegal. For non-`void` functions
|
|
exactly one of [**`RETURN(...)`**](#RETURN), **`LR_RETURN(...)`**,
|
|
[**`LR_THROW(...)`**](#LR_THROW) or [**`THROW(...)`**](#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](http://en.cppreference.com/w/cpp/language/reference),
|
|
to a variable, use
|
|
[`std::ref(value)`](http://en.cppreference.com/w/cpp/utility/functional/ref) or
|
|
[`std::cref(value)`](http://en.cppreference.com/w/cpp/utility/functional/cref)
|
|
for it, or just enclose the value in an extra parenthesis, like this
|
|
[**`.LR_RETURN((value))`**](reference.md/#RETURN).
|
|
|
|
**NOTE!** Any named local objects named in *expr* are captured by reference so
|
|
lifetime management is important.
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(...)`**](#RETURN) which accesses copies of local variables.
|
|
|
|
<A name="LR_SIDE_EFFECT"/>
|
|
|
|
### **`LR_SIDE_EFFECT(`** *expr* **`)`**
|
|
|
|
Used in [expectations](#expectation) to cause side effects for matching calls.
|
|
*expr* is only evaluated when all [**`WITH(...)`**](#WITH) and
|
|
[**`LR_WITH(...)`**](#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(...)`**](#SIDE_EFFECT)
|
|
clauses can be added to a single [expectation](#expectation), and they are
|
|
evaluated in order.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(...)`**](#SIDE_EFFECT) which accesses copies of local
|
|
objects.
|
|
|
|
<A name="LR_THROW"/>
|
|
|
|
### **`LR_THROW(`** *expr* **`)`**
|
|
|
|
Used in [expectations](#expectation) to throw after having evaluated every
|
|
[**`SIDE_EFFECT(...)`**](#SIDE_EFFECT) and
|
|
[**`LR_SIDE_EFFECT(...)`**](#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(...)`**](#THROW),
|
|
[**`LR_RETURN(...)`**](#LR_RETURN) or [**`RETURN(...)`**](#RETURN). Named local
|
|
objects are accessed by reference so lifetime management is important.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(...)`**](#THROW) which accesses copies of local objects.
|
|
|
|
<A name="LR_WITH"/>
|
|
|
|
### **`LR_WITH(`** *expr* **`)`**
|
|
|
|
Used with [expectations](#expectation) to add further conditions for a
|
|
matching call. Typically used when [matchers](#matcher) 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(...)`**](#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:
|
|
|
|
```Cpp
|
|
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](#expectation) could match and
|
|
are disambiguated by **`LR_WITH(...)`** and [**`WITH(...)`**](#WITH) the
|
|
global/static objects will be modified also by those
|
|
[expectations](#expectation) that do not match.
|
|
|
|
See also [**`WITH(...)`**](#WITH) which accesses copies of local objects.
|
|
|
|
<A name="MAKE_CONST_MOCK"/>
|
|
|
|
### **`MAKE_CONST_MOCK(`** *func_name*, *signature* {, *specifiers* } **`)`**
|
|
|
|
Make a `const` [mock function](#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`](http://en.cppreference.com/w/cpp/language/override) or
|
|
[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec).
|
|
|
|
Because of limitations in how the preprocessor works, *signature* **must** be written with
|
|
[trailing return type syntax](https://arne-mertz.de/2016/11/trailing-return-types-everywhere/).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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:
|
|
|
|
```Cpp
|
|
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](#mock_function) 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(...)`**](#MAKE_CONST_MOCKn) to explicitly
|
|
define a nullary mock function.
|
|
|
|
|
|
See also [**`MAKE_MOCK(...)`**](#MAKE_MOCK) for non-`const`
|
|
member functions, and [**`MAKE_CONST_MOCKn(...)`**](#MAKE_CONST_MOCKn) for
|
|
explicit function arity.
|
|
|
|
|
|
<A name="MAKE_CONST_MOCKn"/>
|
|
|
|
### **`MAKE_CONST_MOCKn(`** *func_name*, *signature* {, *specifiers* } **`)`**
|
|
|
|
Make a `const` [mock function](#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`](http://en.cppreference.com/w/cpp/language/override) or
|
|
[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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:
|
|
|
|
```Cpp
|
|
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](#mock_function) from those.
|
|
|
|
See also [**`MAKE_MOCKn(...)`**](#MAKE_MOCKn) for non-`const`
|
|
member functions and [**`MAKE_CONST_MOCK(...)`**`](#MAKE_CONST_MOCK) for
|
|
implicit function arity deduction.
|
|
|
|
|
|
<A name="MAKE_MOCK"/>
|
|
|
|
### **`MAKE_MOCK(`** *func_name*, *signature* {, *specifiers* } **`)`**
|
|
|
|
Make a non-const [mock function](#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`](http://en.cppreference.com/w/cpp/language/override) or
|
|
[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec).
|
|
|
|
Because of limitations in how the preprocessor works, *signature* **must** be written with
|
|
[trailing return type syntax](https://arne-mertz.de/2016/11/trailing-return-types-everywhere/).
|
|
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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:
|
|
|
|
```Cpp
|
|
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](#mock_function) 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(...)`**](#MAKE_MOCKn) to explicitly
|
|
define a nullary mock function.
|
|
|
|
|
|
See also [**`MAKE_CONST_MOCK(...)`**](#MAKE_CONST_MOCK) for `const`
|
|
member functions and [**`MAKE_MOCKn(...)`**](#MAKE_MOCKn) for explicit
|
|
function arity.
|
|
|
|
|
|
<A name="MAKE_MOCKn"/>
|
|
|
|
### **`MAKE_MOCKn(`** *func_name*, *signature* {, *specifiers* } **`)`**
|
|
|
|
Make a non-const [mock function](#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`](http://en.cppreference.com/w/cpp/language/override) or
|
|
[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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:
|
|
|
|
```Cpp
|
|
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](#mock_function) from those.
|
|
|
|
See also [**`MAKE_CONST_MOCKn(...)`**](#MAKE_CONST_MOCKn) for `const`
|
|
member functions and [**`MAKE_MOCK(...)`**`](#MAKE_MOCK) for implicit function
|
|
arity deduction.
|
|
|
|
|
|
<A name="MAKE_STDMETHOD_MOCK"/>
|
|
|
|
### **`MAKE_STDMETHOD_MOCK(`** *func_name*, *signature* {, *specifiers* } **`)`**
|
|
|
|
Make a STDMETHODCALLTYPE [mock function](#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`](http://en.cppreference.com/w/cpp/language/override) or
|
|
[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec).
|
|
|
|
Because of limitations in how the preprocessor works, *signature* **must** be written with
|
|
[trailing return type syntax](https://arne-mertz.de/2016/11/trailing-return-types-everywhere/).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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:
|
|
|
|
```Cpp
|
|
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](#mock_function) 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(...)`**](#MAKE_STDMETHOD_MOCKn) to
|
|
explicitly define a nullary mock function.
|
|
|
|
See also [**`MAKE_STDTMETHOD_MOCKn(...)`**](#MAKE_STDMETHOD_MOCKn) for explicit
|
|
function arity.
|
|
|
|
|
|
<A name="MAKE_STDMETHOD_MOCKn"/>
|
|
|
|
### **`MAKE_STDMETHOD_MOCKn(`** *func_name*, *signature* {, *specifiers* } **`)`**
|
|
|
|
Make a STDMETHODCALLTYPE [mock function](#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`](http://en.cppreference.com/w/cpp/language/override) or
|
|
[`noexcept`](https://en.cppreference.com/w/cpp/language/noexcept_spec).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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:
|
|
|
|
```Cpp
|
|
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](#mock_function) from those.
|
|
|
|
**NOTE!** **`MAKE_STDMETHOD_MOCKn(...)`** only works on Windows.
|
|
|
|
See also [**`MAKE_STDMETHOD_MOCK(...)`**`](#MAKE_STDMETHOD_MOCK) for implicit
|
|
function arity deduction.
|
|
|
|
|
|
<A name="NAMED_ALLOW_CALL"/>
|
|
|
|
### **`NAMED_ALLOW_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**
|
|
|
|
Make a [`std::unique_ptr<trompeloeil::expectation>`](#expectation_type)
|
|
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](#matcher)
|
|
that describes matching calls.
|
|
|
|
This is the same as
|
|
[**`NAMED_REQUIRE_CALL(...)`**](#NAMED_REQUIRE_CALL).[**`TIMES(`**](#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_WITH), [**`LR_SIDE_EFFECT(...)`**](#LR_SIDE_EFFECT),
|
|
[**`LR_RETURN(...)`**](#LR_RETURN) and [**`LR_THROW(...)`**](#LR_THROW) are
|
|
captured by reference so lifetime management is important.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(...)`**](#ALLOW_CALL) which creates an expectation
|
|
that is valid until the end of the surrounding scope.
|
|
|
|
<A name="NAMED_FORBID_CALL"/>
|
|
|
|
### **`NAMED_FORBID_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**
|
|
|
|
Make a [`std::unique_ptr<trompeloeil::expectation>`](#expectation_type)
|
|
disallowing calls to *mock_object*.*func_name*(*parameter_list*) until the
|
|
expectation object is destroyed. *parameter_list* may contain exact values or
|
|
[matchers](#matcher) that describes matching calls.
|
|
|
|
This is the same as
|
|
[**`NAMED_REQUIRE_CALL(...)`**](#NAMED_REQUIRE_CALL).[**`TIMES(`**](#TIMES)
|
|
0 **`)`**, making any matching call an error. This is typically done when a wider
|
|
scope would allow the call. [**`RETURN(...)`**](#RETURN),
|
|
[**`LR_RETURN(...)`**](#LR_RETURN), [**`LR_THROW(...)`**](#LR_THROW) and
|
|
[**`THROW(...)`**](#THROW) are illegal in a **`NAMED_FORBID_CALL(...)`**.
|
|
|
|
**NOTE!** Any named objects referenced in attached
|
|
[**`LR_WITH(...)`**](#LR_WITH) are captured by reference so lifetime management
|
|
is important.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(...)`**](#FORBID_CALL) which creates an
|
|
[expectation](#expectation) that is valid until the end of the surrounding scope.
|
|
|
|
<A name="NAMED_REQUIRE_CALL"/>
|
|
|
|
### **`NAMED_REQUIRE_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**
|
|
|
|
Make a [`std::unique_ptr<trompeloeil::expectation>`](#expectation_type)
|
|
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](#matcher) that describes matching calls.
|
|
|
|
The number of matches required before the [expectation](#expectation) object
|
|
is destroyed can be changed with an optional [**`TIMES(...)`**](#TIMES) clause.
|
|
|
|
**NOTE!** Any named objects referenced in attached
|
|
[**`LR_WITH(...)`**](#LR_WITH), [**`LR_SIDE_EFFECT(...)`**](#LR_SIDE_EFFECT),
|
|
[**`LR_RETURN(...)`**](#LR_RETURN) and [**`LR_THROW(...)`**](#LR_THROW) are
|
|
captured by reference so lifetime management is important.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(...)`**](#REQUIRE_CALL) which creates an
|
|
[expectation](#expectation) that is valid until the end of the surrounding scope.
|
|
|
|
<A name="NAMED_REQUIRE_DESTRUCTION"/>
|
|
|
|
### **`NAMED_REQUIRE_DESTRUCTION(`** *mock_object* **`)`**
|
|
|
|
Create a
|
|
[`std::unique_ptr<trompeloeil::expectation>`](#expectation_type)
|
|
object which reports a violation if the
|
|
[**`deathwatched_type`**](#deathwatched_type) [mock object](#mock_object) is
|
|
not destroyed by the time the `expectation` is destroyed.
|
|
|
|
`#include <trompeloeil/lifetime.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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`](#deathwatched_type)
|
|
[mock object](#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`](#lifetime_monitor_type)
|
|
(subtype of [`expectation`](#expectation_type)) 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(...)`**](#REQUIRE_DESTRUCTION) which places
|
|
a requirement that the [`deathwatched`](#deathwatched_type)
|
|
[mock object](#mock_object) is destroyed before the end of the scope.
|
|
|
|
<A name="REQUIRE_CALL"/>
|
|
|
|
### **`REQUIRE_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**
|
|
|
|
Make an [expectation](#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](#matcher) that describes matching parameter values for the
|
|
[expectation](#expectation).
|
|
|
|
The number of matches required before the [expectation](#expectation) object
|
|
is destroyed can be changed with an optional [**`TIMES(...)`**](#TIMES) clause.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(...)`**](#NAMED_REQUIRE_CALL) which creates an
|
|
[expectation](#expectation) that is held by a
|
|
[`std::unique_ptr<trompeloeil::expectation>`](#expectation_type) which can be stored in test
|
|
fixtures.
|
|
|
|
<A name="REQUIRE_DESTRUCTION"/>
|
|
|
|
### **`REQUIRE_DESTRUCTION(`** *mock_object* **`)`**
|
|
|
|
Create an anonymous [`lifetime_monitor`](#lifetime_monitor_type) which reports
|
|
a violation if the [**`deathwatched`**](#deathwatched_type)
|
|
[mock object](#mock_object) is not destroyed by the end of the scope.
|
|
|
|
`#include <trompeloeil/lifetime.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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`](#deathwatched_type)
|
|
[mock object](#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(...)`**](#NAMED_REQUIRE_DESTRUCTION)
|
|
which creates the requirement that the [`deathwatched`](#deathwatched_type)
|
|
[mock object](#mock_object) is destroyed as a
|
|
[`std::unique_ptr<trompeloeil::lifetime_monitor>`](#lifetime_monitor_type)
|
|
which can be stored in test fixtures.
|
|
|
|
<A name="RETURN"/>
|
|
|
|
### **`RETURN(`** *expr* **`)`**
|
|
|
|
Used in [expectations](#expectation) to set the return value after having
|
|
evaluated every [**`SIDE_EFFECT(...)`**](#SIDE_EFFECT) and
|
|
[**`LR_SIDE_EFFECT(...)`**](#LR_SIDE_EFFECT).
|
|
For `void` functions **`RETURN(...)`** is illegal. For non-`void` functions
|
|
exactly one of [**`LR_RETURN(...)`**](#LR_RETURN), **`RETURN(...)`**,
|
|
[**`LR_THROW(...)`**](#LR_THROW) or [**`THROW(...)`**](#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:
|
|
|
|
```Cpp
|
|
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(...)`**](#LR_RETURN) which accesses local variables
|
|
by reference.
|
|
|
|
<A name="SIDE_EFFECT"/>
|
|
|
|
### **`SIDE_EFFECT(`** *expr* **`)`**
|
|
|
|
Used in [expectations](#expectation) to cause side effects for matching calls.
|
|
*expr* is only evaluated when all [**`WITH(...)`**](#WITH) and
|
|
[**`LR_WITH(...)`**](#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(...)`**](#LR_SIDE_EFFECT)
|
|
clauses can be added to a single [expectation](#expectation), and they are
|
|
evaluated in order.
|
|
|
|
Named local objects accessed here refers to immutable copies.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(...)`**](#LR_SIDE_EFFECT) which accesses local
|
|
objects by reference.
|
|
|
|
<A name="THROW"/>
|
|
|
|
### **`THROW(`** *expr* **`)`**
|
|
|
|
Used in [expectations](#expectation) to throw after having evaluated every
|
|
[**`SIDE_EFFECT(...)`**](#SIDE_EFFECT) and
|
|
[**`LR_SIDE_EFFECT(...)`**](#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_THROW),
|
|
[**`LR_RETURN(...)`**](#LR_RETURN) or [**`RETURN(...)`**](#RETURN).
|
|
|
|
Named local objects here refers to immutable copies.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(...)`**](#LR_THROW) which accesses copies of local objects.
|
|
|
|
<A name="TIMES-and-RT_TIMES"/>
|
|
|
|
### **`TIMES(`** *limits* **`)`** and **`RT_TIMES(`** *limits* **`)`**
|
|
|
|
Used in [**`REQUIRE_CALL(...)`**](#REQUIRE_CALL) and
|
|
[**`NAMED_REQUIRE_CALL(...)`**](#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](#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`](http://en.cppreference.com/w/cpp/language/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(..)`**](#REQUIRE_CALL) or
|
|
[**`NAMED_REQUIRE_CALL(...)`**](#NAMED_REQUIRE_CALL).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(...)`**](#AT_LEAST) and
|
|
[**`AT_MOST(...)`**](#AT_MOST).
|
|
|
|
See also [**`IN_SEQUENCE(...)`**](#IN_SEQUENCE) for information about how
|
|
`.TIMES(...)` and `.RT_TIMES(...)` work together with [**`sequence`**](#sequence_type)
|
|
objects.
|
|
|
|
<A name="WITH"/>
|
|
|
|
### **`WITH(`** *expr* **`)`**
|
|
|
|
Used with [expectations](#expectation) to add further conditions for a
|
|
matching call. Typically used when [matchers](#matcher) 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(...)`**](#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:
|
|
|
|
```Cpp
|
|
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](#expectation) could match and
|
|
are disambiguated by [**`LR_WITH(...)`**](#LR_WITH) and **`WITH(...)`** the
|
|
global/static objects will be modified also by those
|
|
[expectations](#expectation) that do not match.
|
|
|
|
See also [**`LR_WITH(...)`**](#LR_WITH) which accesses local objects by
|
|
reference.
|
|
|
|
## <A name="types_and_templates"/>Types and Templates (alphabetical order)
|
|
|
|
### <A name="deathwatched_type"/>`trompeloeil::deathwatched<T>`
|
|
|
|
Template used when it is necessary to control the life time of a
|
|
[mock object](#mock_object). The macros
|
|
[**`REQUIRE_DESTRUCTION(...)`**](#REQUIRE_DESTRUCTION) and
|
|
[**`NAMED_REQUIRE_DESTRUCTION(...)`**](#NAMED_REQUIRE_DESTRUCTION)
|
|
operates on instances of `trompeloeil::deathwatched<T>`.
|
|
|
|
`#include <trompeloeil/lifetime.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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](#mock_function) on `p`, but
|
|
is required to destroy the [mock object](#mock_object), or a violation will
|
|
be reported.
|
|
|
|
`trompeloeil::deathwatched<T>` inherits from `T`, and the constructor
|
|
accepts any parameters and
|
|
[perfectly forwards](http://www.cppsamples.com/common-tasks/perfect-forwarding.html)
|
|
them to the constructor of `T`. The mock type `T` must have a virtual
|
|
destructor.
|
|
|
|
### <A name="expectation_type"/>`trompeloeil::expectation`
|
|
|
|
Base class for all [expectations](#expectation). The macros
|
|
[**`NAMED_ALLOW_CALL(...)`**](#NAMED_ALLOW_CALL),
|
|
[**`NAMED_FORBID_CALL(...)`**](#NAMED_FORBID_CALL) and
|
|
[**`NAMED_REQUIRE_CALL(...)`**](#NAMED_REQUIRE_CALL) results in a
|
|
[`std::unique_ptr<trompeloeil::expectation>`](http://en.cppreference.com/w/cpp/memory/unique_ptr)
|
|
which you can hold in a variable.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
### <A name="expectation_violation_type"/>`trompeloeil::expectation_violation`
|
|
|
|
The exception type used by default to report violations.
|
|
|
|
```Cpp
|
|
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>`
|
|
|
|
### <A name="lifetime_monitor_type"/>`trompeloeil::lifetime_monitor`
|
|
|
|
The macro [**`NAMED_REQUIRE_DESTRUCTION(...)`**](#NAMED_REQUIRE_DESTRUCTION)
|
|
results in a
|
|
[`std::unique_ptr<trompeloeil::lifetime_monitor>`](http://en.cppreference.com/w/cpp/memory/unique_ptr)
|
|
which you can hold in a variable. `trompeloeil::lifetime_monitor` inherits from
|
|
[`trompeloeil::expectation`](#expectation_type).
|
|
|
|
`#include <trompeloeil/lifetime.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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();
|
|
}
|
|
}
|
|
```
|
|
|
|
### <A name="matcher_type"/>`trompeloeil::matcher`
|
|
|
|
`trompeloeil::matcher` is the base class for all [matchers](#matcher). It does
|
|
not do anything and is solely used in internal
|
|
[`SFINAE`](http://en.cppreference.com/w/cpp/language/sfinae) constructions
|
|
and [tag dispatch](http://www.generic-programming.org/languages/cpp/techniques.php#tag_dispatching)
|
|
|
|
Use it, or [`trompeloeil::typed_matcher<T>`](#typed_matcher), as the base class
|
|
when writing custom [matchers](CookBook.md/#custom_matchers).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
### <A name="mock_interface"/>`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(...)`**](#IMPLEMENT_MOCKn) and
|
|
[**`IMPLEMENT_CONST_MOCKn(...)`**](#IMPLEMENT_CONST_MOCKn) macros.
|
|
The [**`MAKE_MOCK(...)`**](#MAKE_MOCK), [**`MAKE_MOCKn(...)`**](#MAKE_MOCKn),
|
|
[**`MAKE_CONST_MOCK(...)`**](#MAKE_CONST_MOCK) and
|
|
[**`MAKE_CONST_MOCKn(...)`**](#MAKE_CONST_MOCKn) macros can also be used.
|
|
|
|
The interface type `T` must not be final.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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.
|
|
|
|
### <A name="ok_reporter_func"/>`trompeloeil::ok_reporter_func`
|
|
|
|
A type used to pass information to the unit testing frame work that a call to a
|
|
[mock function](#mock_function) has not been reported as a violation.
|
|
|
|
```Cpp
|
|
using trompeloeil::ok_reporter_func = std::function<const char*>;
|
|
```
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
The string passed is the parameters to the expectation. E.g.
|
|
|
|
```Cpp
|
|
struct Mock
|
|
{
|
|
MAKE_MOCK1(func, void(int));
|
|
};
|
|
|
|
TEST(...)
|
|
{
|
|
Mock m;
|
|
REQUIRE_CALL(m, func(3)); // passes "m.func(3)" to OK reporter
|
|
|
|
...
|
|
}
|
|
```
|
|
|
|
### <A name="printer"/> `trompeloeil::printer<T>`
|
|
|
|
`printer<T>` is a type that formats values to strings in reports from *Trompeloeil*.
|
|
|
|
```Cpp
|
|
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](CookBook.md/#custom_formatting).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
### <A name="reporter_func"/>`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](#mock_function).
|
|
|
|
```Cpp
|
|
using trompeloeil::reporter_func = std::function<void(trompeloeil::severity,
|
|
char const *file,
|
|
unsigned long line,
|
|
const std::string& msg)>;
|
|
```
|
|
|
|
See [`trompeloeil::severity`](#severity_type).
|
|
|
|
The parameter `msg` contains detailed information about the violation and
|
|
which (if any) [expectations](#expectation) there are on the
|
|
[mock function](#mock_function).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
### <A name="sequence_type"/>`trompeloeil::sequence`
|
|
|
|
Type of object used for fine-tuned control of sequencing of matched
|
|
[expectations](#expectation).
|
|
|
|
`#include <trompeloeil/sequence.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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(...)`**](#IN_SEQUENCE) macro accepts many
|
|
sequence objects.
|
|
|
|
### <A name="severity_type"/> `trompeloeil::severity`
|
|
|
|
Type used in violation reports to dictate what actions are allowed by the
|
|
report handler.
|
|
|
|
```Cpp
|
|
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`](http://en.cppreference.com/w/cpp/error/terminate) is
|
|
called.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
### <A name="stream_tracer"/>`trompeloeil::stream_tracer`
|
|
|
|
An instance of `trompeloeil::stream_tracer` prints information about
|
|
matched calls to the
|
|
[output stream](http://en.cppreference.com/w/cpp/io/basic_ostream)
|
|
it refers to. `stream_tracer` inherits from
|
|
[`trompeloeil::tracer`](#tracer_type).
|
|
|
|
`#include <trompeloeil/stream_tracer.hpp>`
|
|
|
|
```Cpp
|
|
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`](CookBook.md/#stream_tracer)" in the
|
|
[Cook Book](CookBook.md).
|
|
|
|
### <A name="tracer_type"/>`trompeloeil::tracer`
|
|
|
|
Base class for tracers. Inherit from it when writing custom tracers.
|
|
|
|
`#include <trompeloeil/stream_tracer.hpp>`
|
|
|
|
```Cpp
|
|
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](CookBook.md/#custom_tracer)" in the
|
|
[Cook Book](CookBook.md) for an example.
|
|
|
|
### <A name="typed_matcher"/> `trompeloeil::typed_matcher<T>`
|
|
|
|
Convenience class available when writing custom matchers for a specific
|
|
type. It inherits from [`trompeloeil::matcher`](#matcher_type).
|
|
|
|
See "[Writing custom matchers](CookBook.md/#custom_matchers)" in the
|
|
[Cook Book](CookBook.md) for examples.
|
|
|
|
`#include <trompeloeil/matcher.hpp>`
|
|
|
|
## <A name="functions"/>Functions
|
|
|
|
### <A name="is_satisfied"/> `trompeloeil::expectation::is_satisfied() const`
|
|
|
|
Query an [expectation object](#expectation_type) if it is satisfied, i.e. if
|
|
it will not report a missing call if it is destroyed. If
|
|
[**`.TIMES()`**](#TIMES) is used, this is true if the minimum number of calls
|
|
has been reached.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
```Cpp
|
|
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
|
|
}
|
|
```
|
|
|
|
### <A name="is_saturated"/> `trompeloeil::expectation::is_saturated() const`
|
|
|
|
Query an [expectation object](#expectation_type) if it is saturated, i.e. if
|
|
another call will report an unexpected call. If [**`.TIMES()`**](#TIMES) is
|
|
used, this is true if the maximum number of calls has been reached.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
```Cpp
|
|
...
|
|
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.
|
|
```
|
|
|
|
### <A name="get_lock"/> `trompeloeil::get_lock()`
|
|
|
|
Get the global
|
|
[`recursive_mutex`](http://en.cppreference.com/w/cpp/thread/recursive_mutex)
|
|
used by *Trompeloeil*. The mutex is held until the end of the scope.
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
### <A name="print"/>`trompeloeil::print(std::ostream& os, T const& t)`
|
|
|
|
By default `print()` uses the type [`printer<T>`](#printer) 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>`](#printer) instead, which also works for partial
|
|
specializations. See example in the
|
|
[Cook Book](CookBook.md/#custom_formatting).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
|
|
### <A name="is_null"/>`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](CookBook.md/#custom_matchers).
|
|
|
|
`#include <trompeloeil/mock.hpp>`
|
|
|
|
|
|
### <A name="make_matcher"/>`trompeloeil::make_matcher<Type>(...)`
|
|
|
|
```Cpp
|
|
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](CookBook.md/#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&`](http://en.cppreference.com/w/cpp/io/basic_ostream) and the
|
|
stored values `T&&...` in order as `const&`.
|
|
|
|
Examples are found in the Cook Book under
|
|
[Writing custom matchers](CookBook.md/#custom_matchers)
|
|
|
|
`#include <trompeloeil/matcher.hpp>`
|
|
|
|
|
|
### <A name="set_reporter"/>`trompeloeil::set_reporter(...)`
|
|
|
|
These functions are used to adapt *Trompeloeil* to your unit test framework
|
|
of choice.
|
|
|
|
The default reporter throws
|
|
[`trompeloeil::expectation_violation`](#expectation_violation_type) 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>`
|
|
|
|
```Cpp
|
|
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.
|
|
|
|
```Cpp
|
|
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](#mock_function) that is not
|
|
reported as a violation. By default OK reports are ignored.
|
|
|
|
See [`trompeloeil::severity`](#severity_type) for the rules that it
|
|
dictates.
|
|
|
|
See [`trompeloeil::reporter_func`](#reporter_func) and
|
|
[`trompeloeil::ok_reporter_func`](#ok_reporter_func) for details.
|
|
|
|
The [Cook Book](CookBook.md) lists
|
|
[adapter code](CookBook.md/#unit_test_frameworks) for a number of popular
|
|
unit test frame works.
|
|
|
|
### <A name="is_completed"/> `bool trompeloeil::sequence::is_completed() const`
|
|
|
|
Member function of [`sequence`](#sequence_type) object, used to query if
|
|
the sequence it describes is completed or not.
|
|
|
|
`#include <trompeloeil/sequence.hpp>`
|
|
|
|
Example:
|
|
|
|
```Cpp
|
|
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
|
|
}
|
|
```
|
|
|
|
## <A name="constants"/>Constants
|
|
|
|
### <A name="movable_mock"/> `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()`**](reference.md/#WITH),
|
|
[**`.SIDE_EFFECT()`**](reference.md/#SIDE_EFFECT),
|
|
[**`.RETURN()`**](reference.md/#RETURN) and
|
|
[**`.THROW()`**](reference.md/#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>`
|
|
|
|
```Cpp
|
|
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:
|
|
|
|
```Cpp
|
|
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()`**](reference.md/#NAMED_REQUIRE_CALL),
|
|
[**`NAMED_ALLOW_CALL()`**](reference.md/#NAMED_ALLOW_CALL) or
|
|
[**`NAMED_FORBID_CALL()`**](reference.md/#NAMED_FORBID_CALL) can help, since
|
|
they make the expectation life times more visible.
|