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.
trompeloeil/docs/reference.md

109 KiB

Reference

Notions

Mock function

A mock function is a member function that is mocked with MAKE_MOCK(name, signature), MAKE_MOCKn(name, signature), MAKE_CONST_MOCK(name, signature) or MAKE_CONST_MOCKn(name, signature).

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
  MAKE_CONST_MOCK(cfunc, auto (std::string, int) -> int);
};

Above C is a type that has two mock functions void func(int) and auto cfunc(std::string, int) const -> int. With a mock object of type C it is possible to place expectations on the functions func(...) and cfunc(...).

Mock object

A mock object is an object of a type that has mock functions.

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
};

C obj;

Above, obj is a mock object. It is possible to place expectations on mock functions for the object obj.

Expectation

By default it is illegal to call mock functions. Expectations change that. Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
};

TEST(atest)
{
  C mock_obj;

  REQUIRE_CALL(mock_obj, func(3));

  tested_function(mock_obj);
}

Above mock_obj is a mock object with one mock function void func(int).

The line REQUIRE_CALL(mock_obj, func(3)) places an expectation that mock_obj.func(3) is called before the end of the scope. Unless tested_function(mock_obj) calls mock_obj.func(3) a violation is reported.

The ways to set expectations are:

Each NAMED variant returns an expectation as std::unique_ptr<trompeloeil::expectation> which can be saved in variables for storage in test fixtures or other programmatic lifetime control.

If expectations are not met by the time they go out or scope (or in case of the NAMED variants, when the object held by the std::unique_ptr<> is destroyed) a violation is reported.

By default there is no order imposed on expectations. One way to impose order is through their lifetimes. Another is by using IN_SEQUENCE(...).

If there are several expectations that match the same call, they are tried in the reverse order of creation, and the first found match is accepted. In other words, the last created matching expectation is the one used.

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
};

using trompeloeil::_;

TEST(atest)
{
  C mock_obj;

  ALLOW_CALL(mock_obj, func(_));
  FORBID_CALL(mock_obj, func(3));
  FORBID_CALL(mock_obj, func(4));

  tested_function(mock_obj);
}

Above, the first expectation ALLOW_CALL(...) matches everything using the wildcard trompeloeil::_, but the two FORBID_CALL(...) are created later and are thus matched first. This means that if tested_function(...) calls mock_obj.func(int) with 5, the two FORBID_CALL(...) do not match, but the ALLOW_CALL(...) does, so the call is allowed. A call with 3 or 4, results in a violation is report since a FORBID_CALL(...) is matched.

Matcher

Each parameter in the parameter list of an expectation can be an exact value to match for equality (using operator==,) or a matcher. Matchers check a condition on the parameter value. Trompeloeil provides the matchers

You can also provide your own matchers.

_

Used in the parameter list of an expectation, trompeloeil::_ matches any value of any type.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, int(int));
};

using trompeloeil::_;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, func(_))
    .RETURN(_1 + 1);

  test_function(&mock_obj);
}

Above, mock_obj.func() is allowed to be called with any value, and it will return 1 + the value provided.

If type information is needed, for example to disambiguate overloads, use ANY( type ).

MEMBER_IS( member, matcher )

Used in the parameter list of an expectation to match a member of a passed value using a matcher. The matcher can be a value that can be equality compared with the member, or a matcher like gt( value ). This es especially useful together with the matchers all_of( values ) and any_of( values )

#include <trompeloeil/matcher/member_is.hpp>

Example:

struct xy
{
    int x;
    int y;
};

class C
{
public:
  MAKE_MOCK1(func, void(xy));
};

TEST(atest)
{
  C mock_obj;
  REQUIRE_CALL(mock_obj, func(all_of(MEMBER_IS(&xy::x, gt(0)),
                                     MEMBER_IS(&xy::y, 0))));

  test_function(&mock_obj);
}

Above, the expectation matches only calls to mock_obj.fun(xy coord) with coord.x > 0 && coord.y == 0.

ANY( type )

Used in the parameter list of an expectation to match any value of a specified type. This can be used as an alternative to trompeloeil::_ when it is important to disambiguate between overloads.

#include <trompeloeil/matcher/any.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
  MAKE_MOCK2(func, void(std::string));
};

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, func(ANY(int)));

  test_function(&mock_obj);
}

Above, any call to mock_obj.func(int) is accepted, but calls to mock_obj.func(std::string) renders a violation report since there is no matching expectation.

all_of( values )

Used in the parameter list of an expectation to match a value with all of several provided. By default it matches any parameter type that supports comparison with the values, but an explicit type can be specified if needed for disambiguation. values can be any value that is equality comparable with the type, or other matchers that can be used with the type.

#include <trompeloeil/matcher/set_predicate.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(ifunc, void(int*));
  MAKE_MOCK1(func, void(const char*));
  MAKE_MOCK1(func, void(const std::string&));
};

using trompeloeil::ne;
using trompeloeil::eq;
using trompeloeil::all_of;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, ifunc(all_of(ne(nullptr), *eq(3))));

  std::string expected = "foo";
  REQUIRE_CALL(mock_obj, func(all_of<const char*>(ne(nullptr), expected)));

  test_function(&mock_obj);
}

Above, the first expectation matches only calls to mock_obj.ifunc(int*) with a non-null pointer pointing to the value 3. Any call with a nullptr or a pointer pointing to a value other than 3 renders a violation report since no expectation matches.

The second expectation matches only calls to mock_obj.func(const char*), with a C-string "foo".

any_of( values )

Used in the parameter list of an expectation to match a value with any of several provided. By default it matches any parameter type that supports comparison with the values, but an explicit type can be specified if needed for disambiguation. values can be any value that is equality comparable with the type, or other matchers that can be used with the type.

#include <trompeloeil/matcher/set_predicate.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(ifunc, void(int*));
  MAKE_MOCK1(func, void(const char*));
  MAKE_MOCK1(func, void(const std::string&));
};

using trompeloeil::ne;
using trompeloeil::eq;
using trompeloeil::any_of;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, ifunc(any_of(nullptr, *eq(3))));

  std::string expected = "foo";
  REQUIRE_CALL(mock_obj, func(any_of<const char*>(nullptr, expected)));

  test_function(&mock_obj);
}

Above, the first expectation matches only calls to mock_obj.ifunc(int*) with either a nullptr, or a pointer to the value 3. Any call with a non-null pointer pointing to a value other than 3 renders a violation report since no expectation matches.

The second expectation matches only calls to mock_obj.func(const char*), with either nullptr or a C-string "foo".

eq( value )

Used in the parameter list of an expectation to match a value equal to the one provided. By default it matches any parameter type that supports operator==() with the value, but an explicit type can be specified if needed for disambiguation.

#include <trompeloeil/matcher/compare.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int*));
  MAKE_MOCK1(func, void(const char*));
  MAKE_MOCK1(func, void(const std::string&));
};

using trompeloeil::eq;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, func(*eq(3)));

  std::string expected = "foo";
  REQUIRE_CALL(mock_obj, func(eq<const char*>(expected)));

  test_function(&mock_obj);
}

Above, the first expectation matches only calls to mock_obj.func(int*) with a non-null pointer pointing to the value 3. Any call with a nullptr or a pointer pointing to a value other than 3 renders a violation report since no expectation matches.

The second expectation matches only calls to mock_obj.func(const char*), with a C-string "foo".

ne( value )

Used in the parameter list of an expectation to match a value not equal to the one provided. By default it matches any parameter type that supports operator!=() with the value, but an explicit type can be specified if needed for disambiguation.

#include <trompeloeil/matcher/compare.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(const char*));
  MAKE_MOCK1(func, void(const std::string&));
};

using trompeloeil::ne;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, func(ne(nullptr)));
  REQUIRE_CALL(mock_obj, func(ne<std::string>("")));
  test_function(&mock_obj);
}

Above, the first expectation matches only calls to mock_obj.func(const char*) with non-null pointer. Any call with a nullptr renders a violation report since no expectation matches.

The second expectation matches only calls to mock_obj.func(const std::string&), with a non-empty string.

It is also possible to use *ne(val) to match a pointer to a non-equal value.

gt( value )

Used in the parameter list of an expectation to match a value greater than the one provided. By default it matches any parameter type that supports operator>() with the value, but an explicit type can be specified if needed for disambiguation.

#include <trompeloeil/matcher/compare.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(short));
  MAKE_MOCK1(func, void(int));
  MAKE_MOCK1(func, void(std::string));
};

using trompeloeil::gt;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, func(gt<short>(0)));
  ALLOW_CALL(mock_obj, func(gt("foo")));

  test_function(&mock_obj);
}

Above, the first expectation matches only calls to mock_obj.func(short) with positive values. Any call with 0 or negative, and any calls to mock_obj.func(int) renders a violation report since no expectation matches.

The second expectation matches calls to mock_obj.func(std::string), since std::string is greater-than comparable with a string literal.

It is also possible to use *gt(val) to match a pointer to a greater-than value.

ge( value )

Used in the parameter list of an expectation to match a value greater than on equal to the one provided. By default it matches any parameter type that supports operator>=() with the value, but an explicit type can be specified if needed for disambiguation.

#include <trompeloeil/matcher/compare.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
  MAKE_MOCK1(func, void(short));
  MAKE_MOCK1(func, void(std::string));
};

using trompeloeil::ge;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, func(ge<short>(0)));
  REQUIRE_CALL(mock_obj, func(ge("foo")));

  test_function(&mock_obj);
}

Above, the first expectation matches only calls to mock_obj.func(short) with zero or positive values. Any call with a negative value renders a violation report since no expectation matches.

The second expectation matches only calls to mock_obj.func(std::string), since std::string is greater-than-or-equal-to comparable with string literal.

It is also possible to use *ge(val) to match a pointer to a greater-than or equal value.

lt( value )

Used in the parameter list of an expectation to match a value less than the one provided. By default it matches any parameter type that supports operator<() with the value, but an explicit type can be specified if needed for disambiguation.

#include <trompeloeil/matcher/compare.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(long));
  MAKE_MOCK1(func, void(int));
  MAKE_MOCK1(func, void(const std::string&));
};

using trompeloeil::lt;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, func(lt<int>(0)));
  REQUIRE_CALL(mock_obj, func(lt("foo")));

  test_function(&mock_obj);
}

Above, the first expectation matches only calls to mock_obj.func(int) with negative values. Any call with 0 or positive renders a violation report since no expectation matches.

The second expectation matches calls to mock_obj.func(cost std::string&), since std::string is less-than comparable with string a literal.

It is also possible to use *lt(val) to match a pointer to a less-than value.

le( value )

Used in the parameter list of an expectation to match a value less than or equal to the one provided. By default it matches any parameter type that supports operator<=() with the value, but an explicit type can be specified if needed for disambiguation.

#include <trompeloeil/matcher/compare.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
  MAKE_MOCK1(func, void(short));
  MAKE_MOCK1(func, void(const char*));
};

using trompeloeil::le;
using std::string_literals;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, func(le<short>(0)));
  REQUIRE_CALL(mock_obj, func(le("foo"s)));
  test_function(&mock_obj);
}

Above, first the expectation matches only calls to mock_obj.func(short) with zero or negative values. Any call with a positive value renders a violation report since no expectation matches.

The second expectation matches calls to mock_obj.func(const char*), since a c-string is less-than comparable with a std::string

It is also possible to use *le(val) to match a pointer to a less-than or equal value.

none_of( values )

Used in the parameter list of an expectation to ensure no match between a value and several provided. By default it matches any parameter type that supports comparison with the values, but an explicit type can be specified if needed for disambiguation. values can be any value that is equality comparable with the type, or other matchers that can be used with the type.

#include <trompeloeil/matcher/set_predicate.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(ifunc, void(int*));
  MAKE_MOCK1(func, void(const char*));
  MAKE_MOCK1(func, void(const std::string&));
};

using trompeloeil::ne;
using trompeloeil::eq;
using trompeloeil::none_of;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, ifunc(none_of(nullptr, *eq(3))));

  std::string expected = "foo";
  REQUIRE_CALL(mock_obj, func(none_of<const char*>(nullptr, expected)));

  test_function(&mock_obj);
}

Above, the first expectation matches only calls to mock_obj.ifunc(int*) with a non-null pointer pointer to a value other than 3. Any call with a nullptr, or a pointer pointing to the value 3 renders a violation report since no expectation matches.

The second expectation matches only calls to mock_obj.func(const char*), with a non-null pointer, pointing to a C-string that is not "foo".

re( string )

Used in the parameter list of an expectation to match a string with a regular expression.

#include <trompeloeil/matcher/re.hpp>

re() exists in two flavours.

  • re( string, flags... ) which can match both C-strings (char*, const char*) as well 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()

Example:

class C
{
public:
  MAKE_MOCK1(unique, void(std::string&));
  MAKE_MOCK1(overloaded, void(const char*));
  MAKE_MOCK1(overloaded, void(const std::string&));
};

using trompeloeil::re;

TEST(atest)
{
  C mock_obj;
  REQUIRE_CALL(mock_obj, unique(re("end$", std::regex_constants::icase)));
  REQUIRE_CALL(mock_obj, overloaded(re<const char*>("end", std::regex_constants::match_not_eol)));
  test_function(&mock_obj);
}

Above, test_function(&mock_obj) must call mock_obj.unique() with a string case insensitively matching the regular expression /end$/, and also call mock_obj.overloaded(const char*) with a regular expression matching the regular expression /end/.

It is also possible to use *re(string) to match a pointer to a string with a regular expression, or !re(string) to allow only strings that do not match a regular expression.

range_includes( matchers )

Used in the parameter list of an expectation to match a range with has a set of matchers. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.

#include <trompeloeil/matcher/range.hpp>

range_includes comes in two flavours:

  • range_includes( matchers ) where matchers is one or several values or other matchers like re( string )
  • range_includes( values ) where values is a collection, e.g. a std::vector<> or C-array, of values.

Example using matchers:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::list<int>&));
};

using trompeloeil::gt;
using trompeloeil::range_includes;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, vfunc(range_includes(gt(2), 1)));
  REQUIRE_CALL(mock_obj, ofunc(range_includes<std::list<int>>(1,2,3)));
  test_function(&mock_obj);
}

Above, first the expectation matches only calls to mock_obj.vfunc(const std::vector<int>&) which has at least one element == 1, and at least one element > 2. Any call with a different set of values renders a violation report since no expectation matches.

The second expectation matches calls to mock_obj.ofunc(const std::list<int>&) with at least the values { 1, 2, 3 } (in any order).

Example using a C-array of values:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
};

using trompeloeil::range_includes;

TEST(atest)
{
  C mock_obj;
  int values[] {2, 1 };
  ALLOW_CALL(mock_obj, vfunc(range_includes(values)));
  test_function(&mock_obj);
}

The expectation only matches calls to mock_obj.vfunc() with a vector that holds at least one elemend with the value 1, and at least one element with the value 2.

range_is( matchers )

Used in the parameter list of an expectation to match a range with a set of matchers. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.

#include <trompeloeil/matcher/range.hpp>

range_is comes in two flavours:

  • range_is( matchers ) where matchers is one or several values or other matchers like re( string )
  • range_is( values ) where values is a collection, e.g. a std::vector<> or C-array, of values.

Example using matchers:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::list<int>&));
};

using trompeloeil::le;
using trompeloeil::range_is;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, vfunc(range_is(1, 3, le(0))));
  REQUIRE_CALL(mock_obj, ofunc(range_is<std::list<int>>(1,2,3)));
  test_function(&mock_obj);
}

Above, first the expectation matches only calls to mock_obj.vfunc(const std::vector<int>&) with the values { 1, 3, x }, where x <= 0. Any call with a different set of values renders a violation report since no expectation matches.

The second expectation matches calls to mock_obj.ofunc(const std::list<int>&) with the values { 1, 2, 3 }.

Example using C-array of values:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
};

using trompeloeil::range_is;

TEST(atest)
{
  C mock_obj;
  int expected[] { 1, 2, 3 };
  ALLOW_CALL(mock_obj, vfunc(range_is(expected)));
  test_function(&mock_obj);
}

The expectation only matches calls to mock_obj.vfunc() with a vector holding exactly { 1, 2, 3 }.

range_all_of( matcher )

Used in the parameter list of an expectation to match each element in a range to a matcher or value. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.

#include <trompeloeil/matcher/range.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::list<int>&));
};

using trompeloeil::gt;
using trompeloeil::range_all_of;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, vfunc(range_all_of(gt(0))));
  REQUIRE_CALL(mock_obj, ofunc(range_all_of<std::list<int>>(gt(0))));
  test_function(&mock_obj);
}

Above, first the expectation matches only calls to mock_obj.vfunc(const std::vector<int>&) with values > 0, Any call with a different set of values renders a violation report since no expectation matches.

The second expectation matches calls to mock_obj.ofunc(const std::list<int>&) with values > 0.

The matcher range_all_of always matches an empty range.

range_any_of( matcher )

Used in the parameter list of an expectation to match each element in a range to a matcher or value. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.

#include <trompeloeil/matcher/range.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::list<int>&));
};

using trompeloeil::gt;
using trompeloeil::range_any_of;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, vfunc(range_any_of(gt(0))));
  REQUIRE_CALL(mock_obj, ofunc(range_any_of<std::list<int>>(gt(0))));
  test_function(&mock_obj);
}

Above, first the expectation matches only calls to mock_obj.vfunc(const std::vector<int>&) with at least one values > 0, Any call with a different set of values renders a violation report since no expectation matches.

The second expectation matches calls to mock_obj.ofunc(const std::list<int>&) with at least one value > 0.

The matcher range_any_of does never match an empty range.

range_none_of( matcher )

Used in the parameter list of an expectation to match each element in a range to a matcher or value. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.

#include <trompeloeil/matcher/range.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::list<int>&));
};

using trompeloeil::lt;
using trompeloeil::range_none_of;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, vfunc(range_none_of(0)));
  REQUIRE_CALL(mock_obj, ofunc(range_none_of<std::list<int>>(lt(0))));
  test_function(&mock_obj);
}

Above, first the expectation matches only calls to mock_obj.vfunc(const std::vector<int>&) where none of the values are 0, Any call with a at least one value == 0 renders a violation report since no expectation matches.

The second expectation matches calls to mock_obj.ofunc(const std::list<int>&) where none of the values are < 0.

The matcher range_none_ofl always matches an empty range.

range_is_permutation( matchers )

Used in the parameter list of an expectation to match a range with a set of matchers without regard to order. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.

#include <trompeloeil/matcher/range.hpp>

range_is_permutation comes in two flavours:

  • range_is_permutation( matchers ) where matchers is one or several values or other matchers like re( string )
  • range_is_permutation( values ) where values is a collection, e.g. a std::vector<> or C-array, of values.

Example using matchers:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::list<int>&));
};

using trompeloeil::le;
using trompeloeil::range_is_permutation;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, vfunc(range_is_permutation(le(0), 1, 3)));
  REQUIRE_CALL(mock_obj, ofunc(range_is_permutation<std::list<int>>(1,2,3)));
  test_function(&mock_obj);
}

Above, first the expectation matches only calls to mock_obj.vfunc(const std::vector<int>&) with some permutation of the values { 1, 3, x }, where x <= 0. Any call with a different set of values renders a violation report since no expectation matches.

The second expectation matches calls to mock_obj.ofunc(const std::list<int>&) with a permutation of the values { 1, 2, 3 }.

NOTE! Avoid using range_is_permutation with relational matchers like gt( value ). In order to work with input-ranges, it uses a greedy one-pass algorithm, which may reach different results depending on the order in which the elements are matched. E.g. range_is_permutation(gt(0), gt(1), gt(2)) may or may not match a range {3,2,1}.

Example using a C-array of values:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
};

using trompeloeil::range_is_permutation;

TEST(atest)
{
  C mock_obj;
  int values[] { 1, 2, 3 };
  ALLOW_CALL(mock_obj, vfunc(range_is_permutation(values)));
  test_function(&mock_obj);
}

This only allows calls to mock_obj.vfunc() with a vector holding the values 1, 2, 3, in any order.

range_starts_with( matchers )

Used in the parameter list of an expectation to match the first values in a range to a set of matchers. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.

#include <trompeloeil/matcher/range.hpp>

range_starts_with comes in two flavours:

  • range_starts_with( matchers ) where matchers is one or several values or other matchers like re( string )
  • range_starts_with( values ) where values is a collection, e.g. a std::vector<> or C-array, of values.

Example using matchers:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::list<int>&));
};

using trompeloeil::le;
using trompeloeil::range_starts_with;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, vfunc(range_starts_with(1, le(0))));
  REQUIRE_CALL(mock_obj, ofunc(range_starts_with<std::list<int>>(1,2)));
  test_function(&mock_obj);
}

Above, first the expectation matches only calls to mock_obj.vfunc(const std::vector<int>&) with a vector holding at least two elements, starting with { 1, x, }, where x <= 0. Any call with a different set of values renders a violation report since no expectation matches.

The second expectation matches calls to mock_obj.ofunc(const std::list<int>&) with at least two values, starting with { 1, 2 }.

Example using a C-array with values:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
};

using trompeloeil::range_starts_with;

TEST(atest)
{
  C mock_obj;
  int first_values[]{1,2};
  ALLOW_CALL(mock_obj, vfunc(range_starts_with(first_values)));
  test_function(&mock_obj);
}

The example above matches only calls to mock_obj.vfunc() with a vector which starts with the values {1, 2}.

range_ends_with( matchers )

Used in the parameter list of an expectation to match the last values in a range to a set of matchers. By default it can match any range-like type, but it can be explicitly disambiguated by providing a type to match for.

#include <trompeloeil/matcher/range.hpp>

range_ends_with comes in two flavours:

  • range_ends_with( matchers ) where matchers is one or several values or other matchers like re( string )
  • range_ends_with( values ) where values is a collection, e.g. a std::vector<> or C-array, of values.

Example using matchers:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::vector<int>&));
  MAKE_MOCK1(ofunc, void(const std::list<int>&));
};

using trompeloeil::le;
using trompeloeil::range_ends_with;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, vfunc(range_ends_with(1, le(0))));
  REQUIRE_CALL(mock_obj, ofunc(range_ends_with<std::list<int>>(1,2)));
  test_function(&mock_obj);
}

Above, first the expectation matches only calls to mock_obj.vfunc(const std::vector<int>&) with a vector holding at least two elements, ending with { 1, x, }, where x <= 0. Any call with a different set of values renders a violation report since no expectation matches.

The second expectation matches calls to mock_obj.ofunc(const std::list<int>&) with at least two values, ending with { 1, 2 }.

Example using a C-array of values:

class C
{
public:
  MAKE_MOCK1(vfunc, void(const std::vector<int>&));
};

using trompeloeil::range_ends_with;

TEST(atest)
{
  C mock_obj;
  int tail[]{2,1,0};
  ALLOW_CALL(mock_obj, vfunc(range_ends_with(tail)));
  test_function(&mock_obj);
}

The example above only matches calls to mock_obj.vfunc() with a vector with 2,1,0 as the last elements.

* matcher

Used in the parameter list of an expectation together with a matcher, to match a value pointed to by a pointer. A nullptr value fails the matcher.

#include <trompeloeil/matcher/deref.hpp>

Example:

struct C {
  MAKE_MOCK1(func, void(int*));
};

using trompeloeil::eq; // matching equal values

TEST(atest)
{
  C mock_obj;
  REQUIRE_CALL(mock_obj, func(*eq(3)));
  test_function(&mock_obj);
}

Above, test_function(&mock_obj) must call mock_obj.func() with a pointer to the value 3.

! matcher

Used in the parameter list of an expectation together with a matcher, to negate a matcher, i.e. to fail what the matcher allows, and to allow what the matcher fails.

#include <trompeloeil/matcher/not.hpp>

Example:

struct C {
  MAKE_MOCK1(func, void(const std::string&));
};

using trompeloeil::re; // matching regular expressions

TEST(atest)
{
  C mock_obj;
  REQUIRE_CALL(mock_obj, func(!re("^foo")));
  test_function(&mock_obj);
}

Above, test_function(&mock_obj) must call mock_obj.func() with a string that does not begin with "foo".

Macros

ALLOW_CALL( mock_object, func_name(parameter_list))

Make an expectation that mock_object.func_name(parameter_list) may be called zero or more times until the end of the surrounding scope. parameter_list may contain exact values or matchers that describes matching calls.

This is the same as REQUIRE_CALL(...).TIMES( 0,infinity ).

#include <trompeloeil/mock.hpp>

Matches any number of times, but is not required to match. (actually the limit is 0..~0ULL, but that is for all practical purposes "infinity")

Example:

class C
{
public:
  MAKE_MOCK1(func, int(int));
};

using trompeloeil::_;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, func(_))
    .RETURN(_1 + 1);

  test_function(&mock_obj);
}

Above ALLOW_CALL(mock_obj, func(_)) places an expectation that mock_obj.func() may be called any number of times with any parameter value and will always return the parameter value + 1. test_function(...) is allowed to call mock_obj.func() any number of times (including no call at all).

The expectation is valid until the end of the scope, which in the example above is until after the return from test_function(...).

See also NAMED_ALLOW_CALL(...) which creates an expectation as a std::unique_ptr<trompeloeil::expectation> which can be stored in test fixtures or otherwise have its lifetime programmatically controlled.

ANY( type )

A matcher for use in the parameter list of an expectation to disambiguate overloaded functions on type when the exact value is unimportant. See the matcher ANY( type ) above.

#include <trompeloeil/matcher/any.hpp>

AT_LEAST( number )

Used in TIMES(...) to set the range number..infinity. number must be constexpr.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
};

using trompeloeil::_;

TEST(atest)
{
  C mock_obj;
  REQUIRE_CALL(mock_obj, func(_))
    .TIMES(AT_LEAST(3));
  tested_function(&mock_obj);
}

Above, the line TIMES(AT_LEAST(3)) modifies the expectation such that mock_obj.func() must be called 3 times or more, before the end of the scope, or a violation is reported.

In reality the upper limit is ~0ULL, but that is for all practical purposes "infinity".

AT_MOST( number )

Used in TIMES(...) to set the range 0..number. number must be constexpr.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
};

using trompeloeil::_;

TEST(atest)
{
  C mock_obj;
  REQUIRE_CALL(mock_obj, func(_))
    .TIMES(AT_MOST(3));
  tested_function(&mock_obj);
}

Above, the line TIMES(AT_MOST(3)) modifies the expectation such that mock_obj.func() must be called 3 times or less (including no call at all) before the end of the scope, or a violation is reported.

CO_RETURN( expr )

Used in expectations to set the return value from a coroutine. Note that when SIDE_EFFECT(...) and LR_SIDE_EFFECT(...) are executed depends on the behaviour of the coroutine promise type. This code may alter out-parameters.

#include <trompeloeil/coro.hpp>

Coroutines are supported if the compiler defines the __cpp_impl_coroutines feature test macro.

NOTE! Be very extra careful with lifetime issues when dealing with coroutines.

CO_THROW( expr )

Used in expectations to throw an exception from a coroutine. Note that when any SIDE_EFFECT(...) and LR_SIDE_EFFECT(...) are executed depends on the behaviour of the coroutine promise type. This code may alter out-parameters.

#include <trompeloeil/coro.hpp>

Coroutines are supported if the compiler defines the __cpp_impl_coroutines feature test macro.

NOTE! Be very extra careful with lifetime issues when dealing with coroutines.

CO_YIELD( expr )

Used in expectations with a coroutine type that can co_yield. You can add several CO_YIELD to the same expectation, and the values will be yielded one at the time, in the order they are listed. Note that CO_RETURN( expr ) or LR_CO_RETURN( expr ) is still needed.

See also LR_CO_YIELD( expr ]

#include <trompeloeil/coro.hpp>

Coroutines are supported if the compiler defines the __cpp_impl_coroutines feature test macro.

NOTE! Be very extra careful with lifetime issues when dealing with coroutines.

FORBID_CALL( mock_object, func_name(parameter_list))

Make an expectation that mock_object.func_name(parameter_list) must not be called until the end of the scope. parameter_list may contain exact values or matchers that describes matching calls.

This is the same as REQUIRE_CALL(...).TIMES( 0 ), making any matching call an error. This is often done in a narrow scope where the wider scope would allow the call. LR_RETURN(...), RETURN(...), LR_THROW(...) and THROW(...) are illegal in a FORBID_CALL(...).

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
};

using trompeloeil::_;

TEST(atest)
{
  C mock_obj;
  ALLOW_CALL(mock_obj, func(_));

  tested_function(1, &mock_obj);

  {
    FORBID_CALL(mock_obj, func(2));

    tested_function(2, &mock_obj);
  }

  tested_function(3, &mock_obj);
}

Above, the mock function C::func(int) may be called with any value for mock_obj, except in the scope of the tested_function(2, &mock_obj), where mock_obj.func(2) would lead to a violation being reported. At tested_function(3, &mock_obj) any value is allowed again.

See also NAMED_FORBID_CALL(...) which creates an expectation as a std::unique_ptr<trompeloeil::expectation> which can be stored in test fixtures or otherwise have its lifetime programmatically controlled.

IMPLEMENT_CONST_MOCKn( func_name {, specifiers } )

Make a const mock function implementation of the virtual function named func_name from the inherited interface. This macro is only usable with virtual non-final functions, and only when used with mock_interface<T>, where T is the interface.

specifiers is an optional list which may include attributes or specifiers like noexcept.

#include <trompeloeil/mock.hpp>

Example:

class I
{
public:
  virtual ~I() = default;
  virtual int func(int, const std::vector<int>&)) const = 0;
};

class C : public trompeloeil::mock_interface<I>
{
public:
  IMPLEMENT_CONST_MOCK2(func);
};

Above, class C will effectively become:

class C : public trompeloeil::mock_interface<I>
{
public:
  int func(int, const std::vector<int>&) const override;
};

It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.

NOTE! IMPLEMENT_CONST_MOCKn(...) cannot handle overloaded functions.

See also IMPLEMENT_MOCKn(...) for non-const member functions.

See also MAKE_MOCK(...), MAKE_MOCKn(...), MAKE_CONST_MOCK(...) and MAKE_CONST_MOCKn(...) for making mock implementations of any member functions.

IMPLEMENT_MOCKn( func_name {, specifiers } )

Make a non-const mock function implementation of the virtual function named func_name from the inherited interface. This macro is only usable with virtual non-final functions, and only when used with mock_interface<T>, where T is the interface.

specifiers is an optional list which may include attributes or specifiers like noexcept.

#include <trompeloeil/mock.hpp>

Example:

class I
{
public:
  virtual ~I() = default;
  virtual int func(int, const std::vector<int>&)) = 0;
};

class C : public trompeloeil::mock_interface<I>
{
public:
  IMPLEMENT_MOCK2(func1);
};

Above, class C will effectively become:

class C : public trompeloeil::mock_interface<I>
{
public:
  int func(int, const std::vector<int>&) override;
};

It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.

NOTE! IMPLEMENT_MOCKn(...) cannot handle overloaded functions.

See also IMPLEMENT_CONST_MOCKn(...) for const member functions.

See also MAKE_CONST_MOCKn(...) for const member functions.

IMPLEMENT_STDMETHOD_MOCKn( func_name {, specifiers } )

Make a STDMETHODCALLTYPE mock function implementation of the virtual function named func_name from the inherited interface. This macro is only usable with virtual non-final functions, and only when used with mock_interface<T>, where T is the interface.

specifiers is an optional list which may include attributes or specifiers like noexcept.

#include <trompeloeil/mock.hpp>

Example:

class I
{
public:
  virtual ~I() = default;
  virtual int STDMETHODCALLTYPE func(int, const std::vector<int>&)) const = 0;
};

class C : public trompeloeil::mock_interface<I>
{
public:
  IMPLEMENT_STDMETHOD_MOCK2(func);
};

Above, class C will effectively become:

class C : public trompeloeil::mock_interface<I>
{
public:
  int STDMETHODCALLTYPE func(int, const std::vector<int>&) const override;
};

It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.

NOTE! IMPLEMENT_STDMETHOD_MOCKn(...) cannot handle overloaded functions.

NOTE! IMPLEMENT_STDMETHOD_MOCKn(...) only works on Windows.

See also MAKE_STDMETHOD_MOCKn(...)

IN_SEQUENCE( seq... )

Where seq... is one or more instances of trompeloeil::sequence. Impose an order in which expectations and destruction of deathwatched_type objects must match. Several sequences can be parallel and interleaved. A sequence for an expectation can move forward to the next once the lower limit from TIMES(...) is reached (defaults to 1). This means that if the lower limit is 0 (see ALLOW_CALL(...)), the expectation may be skipped in the sequence.

#include <trompeloeil/sequence.hpp>

Example:

class Mock
{
public:
  MAKE_MOCK1(func, void(int));
  MAKE_MOCK1(func, void(const std::string&));
};

class ephemeral
{
public:
  virtual ~ephemeral() {};
};

TEST(atest)
{
  Mock m[2];
  auto e = new trompeloeil::deathwatched<ephemeral>;

  trompeloeil::sequence seq1, seq2;

  REQUIRE_CALL(m[0], func(ANY(int))
    .IN_SEQUENCE(seq1, seq2);

  REQUIRE_CALL(m[0], func(ANY(const std::string&))
    .IN_SEQUENCE(seq1);

  REQUIRE_CALL(m[1], func(ANY(const std::string&))
    .IN_SEQUENCE(seq2);

  REQUIRE_CALL(m[1], func(ANY(int))
    .IN_SEQUENCE(seq1, seq2);

  REQUIRE_DESTRUCTION(*e)
    .IN_SEQUENCE(seq1, seq2);

  tested_func(&m[0], &m[1], e);
}

All sequence objects are listed in the first REQUIRE_CALL(...), thus it must be the first expectation matched. Likewise all sequences are listed in the last REQUIRE_CALL(...), so it must be last expectation matched. The intermediate expectations has one sequence object each, thus they have no matching order imposed between them. Last of all is the REQUIRE_DESTRUCTION(...), which also lists all sequence objects and must happen after all other expectations are fulfilled.

The above allows the following two sequences only.

  • m[0].func(int) -> m[0].func(string) -> m[1].func(string) -> m[1].func(int) -> delete e
  • m[0].func(int) -> m[1].func(string) -> m[0].func(string) -> m[1].func(int) -> delete e

Any other sequence of calls renders a violation report.

Note that .IN_SEQUENCE() in combination with .TIMES(...) is greedy. It will stay on on the same expectation as long as it matches, and will leave for the next step in the sequence only when the upper bound from .TIMES(...) is reached, or a different expectation matches.

Example:

class Mock
{
public:
  MAKE_MOCK1(func, void(int));
};

TEST(a_test)
{
  Mock m;
  trompeloeil::sequence seq;
  
  REQUIRE_CALL(m, func(0))
    .IN_SEQUENCE(seq)
    .TIMES(1, 5);
  
  ALLOW_CALL(m, func(0))
    .IN_SEQUENCE(seq)
    .SIDE_EFFECT(std::cout << "extra\n");
  
  REQUIRE_CALL(m, func(1))
    .IN_SEQUENCE(seq);
  
  test_func(m);
}

The expectation REQUIRE_CALL(m, func(0)) stays in effect until either matched 5 times, or a call to m.func(1) has been made. After a call to m.func(1), no call to m.func(0) is allowed.

The function test_func() must call m.func(0) at least once, and end with m.func(1). If m.func(0) is called more than 5 times, each call prints "extra" on std::cout.

LR_CO_RETURN( expr )

Used in expectations to set the return value from a coroutine. Note that when any SIDE_EFFECT(...) and LR_SIDE_EFFECT(...) are executed depends on the behaviour of the coroutine promise type. This code may alter out-parameters.

#include <trompeloeil/coro.hpp>

Coroutines are supported if the compiler defines the __cpp_impl_coroutines feature test macro.

NOTE! Any named local objects named in expr are captured by reference so lifetime management is important.

NOTE! Be very extra careful with lifetime issues when dealing with coroutines.

LR_CO_THROW( expr )

Used in expectations to throw an exception from a coroutine. Note that when any SIDE_EFFECT(...) and LR_SIDE_EFFECT(...) are executed depends on the behaviour of the coroutine promise type. This code may alter out-parameters.

#include <trompeloeil/coro.hpp>

Coroutines are supported if the compiler defines the __cpp_impl_coroutines feature test macro.

NOTE! Any named local objects named in expr are captured by reference so lifetime management is important.

NOTE! Be very extra careful with lifetime issues when dealing with coroutines.

LR_CO_YIELD( expr )

Used in expectations with a coroutine type that can co_yield. You can add several LR_CO_YIELD to the same expectation, and the values will be yielded one at the time, in the order they are listed. Note that CO_RETURN( expr ) or LR_CO_RETURN( expr ) is still needed.

See also CO_YIELD( expr ]

#include <trompeloeil/coro.hpp>

Coroutines are supported if the compiler defines the __cpp_impl_coroutines feature test macro.

NOTE! Any named local objects named in expr are captured by reference so lifetime management is important.

NOTE! Be very extra careful with lifetime issues when dealing with coroutines.

LR_RETURN( expr )

Used in expectations to set the return value after having evaluated every SIDE_EFFECT(...) and LR_SIDE_EFFECT(...). For void functions LR_RETURN(...) is illegal. For non-void functions exactly one of RETURN(...), LR_RETURN(...), LR_THROW(...) or THROW(...) is required. expr may refer to parameters in the call with their positional names _1, _2, etc. This code may alter out-parameters.

#include <trompeloeil/mock.hpp>

If you need to return an lvalue-reference, to a variable, use std::ref(value) or std::cref(value) for it, or just enclose the value in an extra parenthesis, like this .LR_RETURN((value)).

NOTE! Any named local objects named in expr are captured by reference so lifetime management is important.

Example:

class C
{
public:
  MAKE_MOCK1(func, int&(unsigned));
};

TEST(atest)
{
  C mock_obj;

  int rv = 3;
  ALLOW_CALL(mock_obj, func(0))
    .LR_RETURN(std::ref(rv)); // reference to captured local variable

  rv = 4;
  test_func(&mock_obj);
}

Above, the LR_RETURN(...) clause tells matching calls of mock_obj.func(...) to return a reference to the local variable rv. Since LR_RETURN(...) accesses local variables by reference, the value of the returned reference will be 4 if called from within test_func(...).

See also RETURN(...) which accesses copies of local variables.

LR_SIDE_EFFECT( expr )

Used in expectations to cause side effects for matching calls. expr is only evaluated when all WITH(...) and LR_WITH(...) clauses are matched. expr may refer to parameters in the call with their positional names _1, _2, etc. This code may alter out-parameters. Several LR_SIDE_EFFECT(...) and SIDE_EFFECT(...) clauses can be added to a single expectation, and they are evaluated in order.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(unsigned));
};

TEST(atest)
{
  C mock_obj;
  unsigned sum = 0;
  ALLOW_CALL(mock_obj, func(ANY(unsigned))
    .LR_SIDE_EFFECT(sum += _1);

  tested_func(&mock_obj);

  std::cout << "parameter sum=" << sum << "\n";
}

Above, tested_func(&mock_obj) is allowed to call C::func(int) any number of times on mock_obj. Each time a side effect is that the local variable sum gets the parameter value added to it. Since LR_SIDE_EFFECT(...) refers to sum by reference, it is the actual local variable that is changed is every call.

See also SIDE_EFFECT(...) which accesses copies of local objects.

LR_THROW( expr )

Used in expectations to throw after having evaluated every SIDE_EFFECT(...) and LR_SIDE_EFFECT(...) for a matching call. expr may refer to parameters in the call with their positional names _1, _2, etc. This code may alter out-parameters. It is not legal to combine LR_THROW(...) with any of THROW(...), LR_RETURN(...) or RETURN(...). Named local objects are accessed by reference so lifetime management is important.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(unsigned));
};

TEST(atest)
{
  C mock_obj;
  const char* what="";

  ALLOW_CALL(mock_obj, func(3))
    .LR_THROW(std::invalid_argument(what));

  what = "nonsense";
  tested_func(&mock_obj);
}

Above, LR_THROW(std::invalid_argument(what)) will refer to the C-string what with the value it has at the time of a call to mock_obj.func(3), i.e. "nonsense" if tested_func() does the call.

See also THROW(...) which accesses copies of local objects.

LR_WITH( expr )

Used with expectations to add further conditions for a matching call. Typically used when matchers are used for the parameters, and often when the condition requires several parameter values together. expr can refer to parameters in the call with their positional names _1, _2, etc. Even if the function signature has parameters as non-const references, they are immutable in this context. Several LR_WITH(...) and WITH(...) clauses can be added to a single expectation and they are tried in the order they are added until one has failed, or they all have passed.

Named local objects are accessed by reference so lifetime management is important.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(const char*));
};

using trompeloeil::_;

TEST(atest)
{
  C mock_obj;

  const char buff[] = "string";

  REQUIRE_CALL(mock_obj, func(_))
    .LR_WITH(_1 == buff);

  tested_func(buff, &mock_obj);
}

Above, LR_WITH(_1 == buff) checks the condition that the const char* parameter is the same pointer value as the address to the local array buff.

NOTE! It is legal, but a very bad idea, to modify global/static objects in LR_WITH(...). If several expectations could match and are disambiguated by LR_WITH(...) and WITH(...) the global/static objects will be modified also by those expectations that do not match.

See also WITH(...) which accesses copies of local objects.

MAKE_CONST_MOCK( func_name, signature {, specifiers } )

Make a const mock function named func_name. It is a good idea for this to implement a pure virtual function from an interface, but it is not a requirement. n is the number of parameters in signature. specifiers is an optional list which may include attributes or specifiers like override or noexcept.

Because of limitations in how the preprocessor works, signature must be written with trailing return type syntax.

#include <trompeloeil/mock.hpp>

Example:

class I
{
public:
  virtual ~I() = default;
  virtual auto func1(int, const std::vector<int>&)) const -> int = 0;
};

class C
{
public:
  MAKE_CONST_MOCK(func1, auto (int, const std::vector<int>&) -> int, override);
  MAKE_CONST_MOCK(func2, auto (std::string) -> int);
};

Above, class C will effectively become:

class C : public I
{
public:
  auto func1(int, const std::vector<int>&) const -> int override;
  auto func2(std::string) const -> int;
};

It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.

Note! The preprocessor is limited and can only handle nullary functions, i.e. functions that do not accept any arguments, in some cases.

  • MSVC handles nullary functions when compiling with /Zc:preprocessor with MSVC 19.40 (VS 17.10) or later.

  • Gcc and Clang always handles nullary functions when compiling with C++20 or later, and when enabling a gcc extension by defining the macro TROMPELOEIL_HAS_GCC_PP before #include:ing the trompeloeil headers, and compiling with -std=gnu++11, -std=gnu++14 or -std=gnu++17.

Otherwise, use MAKE_CONST_MOCK0(...) to explicitly define a nullary mock function.

See also MAKE_MOCK(...) for non-const member functions, and MAKE_CONST_MOCKn(...) for explicit function arity.

MAKE_CONST_MOCKn( func_name, signature {, specifiers } )

Make a const mock function named func_name. It is a good idea for this to implement a pure virtual function from an interface, but it is not a requirement. n is the number of parameters in signature. specifiers is an optional list which may include attributes or specifiers like override or noexcept.

#include <trompeloeil/mock.hpp>

Example:

class I
{
public:
  virtual ~I() = default;
  virtual int func1(int, const std::vector<int>&)) const = 0;
};

class C
{
public:
  MAKE_CONST_MOCK2(func1, int(int, const std::vector<int>&), override);
  MAKE_CONST_MOCK1(func2, int(std::string));
};

Above, class C will effectively become:

class C : public I
{
public:
  int func1(int, const std::vector<int>&) const override;
  int func2(std::string) const;
};

It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.

See also MAKE_MOCKn(...) for non-const member functions and MAKE_CONST_MOCK(...)` for implicit function arity deduction.

MAKE_MOCK( func_name, signature {, specifiers } )

Make a non-const mock function named func_name. It is a good idea for this to implement a pure virtual function from an interface, but it is not a requirement. n is the number of parameters in signature. specifiers is an optional list which may include attributes or specifiers like override or noexcept.

Because of limitations in how the preprocessor works, signature must be written with trailing return type syntax.

#include <trompeloeil/mock.hpp>

Example:

class I
{
public:
  virtual ~I() = default;
  virtual auto func1(int, const std::vector<int>&)) -> int = 0;
};

class C : public I
{
public:
  MAKE_MOCK(func1, auto (int, const std::vector<int>&) -> int, override);
  MAKE_MOCK(func2, auto (std::string) -> int);
};

Above, class C will effectively become:

class C : public I
{
public:
  auto func1(int, const std::vector<int>&) -> int override;
  auto func2(std::string) -> int;
};

It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.

Note! The preprocessor is limited and can only handle nullary functions, i.e. functions that do not accept any arguments, in some cases.

  • MSVC handles nullary functions when compiling with /Zc:preprocessor with MSVC 19.40 (VS 17.10) or later.

  • Gcc and Clang always handles nullary functions when compiling with C++20 or later, and when enabling a gcc extension by defining the macro TROMPELOEIL_HAS_GCC_PP before #include:ing the trompeloeil headers, and compiling with -std=gnu++11, -std=gnu++14 or -std=gnu++17.

Otherwise, use MAKE_MOCK0(...) to explicitly define a nullary mock function.

See also MAKE_CONST_MOCK(...) for const member functions and MAKE_MOCKn(...) for explicit function arity.

MAKE_MOCKn( func_name, signature {, specifiers } )

Make a non-const mock function named func_name. It is a good idea for this to implement a pure virtual function from an interface, but it is not a requirement. n is the number of parameters in signature. specifiers is an optional list which may include attributes or specifiers like override or noexcept.

#include <trompeloeil/mock.hpp>

Example:

class I
{
public:
  virtual ~I() = default;
  virtual int func1(int, const std::vector<int>&)) = 0;
};

class C : public I
{
public:
  MAKE_MOCK2(func1, int(int, const std::vector<int>&), override);
  MAKE_MOCK1(func2, int(std::string));
};

Above, class C will effectively become:

class C : public I
{
public:
  int func1(int, const std::vector<int>&) override;
  int func2(std::string);
};

It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.

See also MAKE_CONST_MOCKn(...) for const member functions and MAKE_MOCK(...)` for implicit function arity deduction.

MAKE_STDMETHOD_MOCK( func_name, signature {, specifiers } )

Make a STDMETHODCALLTYPE mock function named func_name. It is a good idea for this to implement a pure virtual function from an interface, but it is not a requirement. n is the number of parameters in signature. specifiers is an optional list which may include attributes or specifiers like override or noexcept.

Because of limitations in how the preprocessor works, signature must be written with trailing return type syntax.

#include <trompeloeil/mock.hpp>

Example:

class I
{
public:
  virtual ~I() = default;
  virtual auto STDMETHODCALLTYPE func1(int, const std::vector<int>&)) -> int = 0;
};

class C : public I
{
public:
  MAKE_STDMETHOD_MOCK(func1, auto (int, const std::vector<int>&) -> int, override);
  MAKE_STDMETHOD_MOCK(func2, auto (std::string) -> int);
};

Above, class C will effectively become:

class C : public I
{
public:
  auto STDMETHODCALLTYPE func1(int, const std::vector<int>&) -> int override;
  auto STDMETHODCALLTYPE func2(std::string) -> int;
};

It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.

NOTE! MAKE_STDMETHOD_MOCK(...) only works on Windows.

NOTE! The preprocessor is limited and can only handle nullary functions, i.e. functions that do not accept any arguments, in some cases.

  • MSVC handles nullary functions when compiling with /Zc:preprocessor with MSVC 19.40 (VS 17.10) or later.

  • Gcc and Clang always handles nullary functions when compiling with C++20 or later, and when enabling a gcc extension by defining the macro TROMPELOEIL_HAS_GCC_PP before #include:ing the trompeloeil headers, and compiling with -std=gnu++11, -std=gnu++14 or -std=gnu++17.

Otherwise, use MAKE_STDMETHOD_MOCK0(...) to explicitly define a nullary mock function.

See also MAKE_STDTMETHOD_MOCKn(...) for explicit function arity.

MAKE_STDMETHOD_MOCKn( func_name, signature {, specifiers } )

Make a STDMETHODCALLTYPE mock function named func_name. It is a good idea for this to implement a pure virtual function from an interface, but it is not a requirement. n is the number of parameters in signature. specifiers is an optional list which may include attributes or specifiers like override or noexcept.

#include <trompeloeil/mock.hpp>

Example:

class I
{
public:
  virtual ~I() = default;
  virtual int STDMETHODCALLTYPE func1(int, const std::vector<int>&)) = 0;
};

class C : public I
{
public:
  MAKE_STDMETHOD_MOCK2(func1, int(int, const std::vector<int>&), override);
  MAKE_STDMETHOD_MOCK1(func2, int(std::string));
};

Above, class C will effectively become:

class C : public I
{
public:
  int STDMETHODCALLTYPE func1(int, const std::vector<int>&) override;
  int STDMETHODCALLTYPE func2(std::string);
};

It is not possible to mock operators, constructors or the destructor, but you can call mock functions from those.

NOTE! MAKE_STDMETHOD_MOCKn(...) only works on Windows.

See also MAKE_STDMETHOD_MOCK(...)` for implicit function arity deduction.

NAMED_ALLOW_CALL( mock_object, func_name(parameter_list))

Make a std::unique_ptr<trompeloeil::expectation> allowing mock_object.func_name(parameter_list) to be called zero or more times until the expectation object is destroyed. parameter_list may contain exact values or matchers that describes matching calls.

This is the same as NAMED_REQUIRE_CALL(...).TIMES( 0,infinity ).

Matches any number of times, but is not required to match. (Actually the limit is 0..~0ULL, but that is for all practical purposes "infinity".)

NOTE! Any named objects referenced in attached LR_WITH(...), LR_SIDE_EFFECT(...), LR_RETURN(...) and LR_THROW(...) are captured by reference so lifetime management is important.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
};

using trompeloeil::gt;
using trompeloeil::lt;
using expectation = std::unique_ptr<trompeloeil::expectation>;

TEST(atest)
{
  C mock_obj;

  expectation x1 = NAMED_ALLOW_CALL(mock_obj, func(gt(0));

  test_function(0, &mock_obj);

  expectation x2 = NAMED_ALLOW_CALL(mock_obj, func(lt(0));

  test_function(1, &mock_obj);

  x1.reset(); // no longer allow calls with positive values

  test_function(2, &mock_obj);
}

Above each NAMED_ALLOW_CALL(mock_obj, func(...)) creates an expectation that mock_obj.func() may be called any number of times. Each expectation is valid for the lifetime of the expectation object. In the example above, this means that x1 is valid for the first two calls to test_function(...), while x2 is valid for the last two calls to test_function(...).

See also ALLOW_CALL(...) which creates an expectation that is valid until the end of the surrounding scope.

NAMED_FORBID_CALL( mock_object, func_name(parameter_list))

Make a std::unique_ptr<trompeloeil::expectation> disallowing calls to mock_object.func_name(parameter_list) until the expectation object is destroyed. parameter_list may contain exact values or matchers that describes matching calls.

This is the same as NAMED_REQUIRE_CALL(...).TIMES( 0 ), making any matching call an error. This is typically done when a wider scope would allow the call. RETURN(...), LR_RETURN(...), LR_THROW(...) and THROW(...) are illegal in a NAMED_FORBID_CALL(...).

NOTE! Any named objects referenced in attached LR_WITH(...) are captured by reference so lifetime management is important.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
}

using trompeloeil::_;
using trompeloeil::gt;
using trompeloeil::lt;

using expectation = std::unique_ptr<trompeloeil::expectation>;

TEST(atest)
{
  C mock_obj;

  ALLOW_CALL(mock_obj, func(_));

  expectation x1 = NAMED_FORBID_CALL(mock_obj, func(gt(0));

  test_function(0, &mock_obj);

  expectation x2 = NAMED_FORBID_CALL(mock_obj, func(lt(0));

  test_function(1, &mock_obj);

  x1.reset(); // allow calls with positive values again

  test_function(2, &mock_obj);
}

Above, calls to mock_obj.func() are generally allowed throughout the test. However, x1 imposes a restriction that calls with positive values are illegal, and that restriction is in place for the first two calls to test_function(...). x2 imposes a restrictions that calls with negative values are illegal, and that restriction is in place for the last two calls to test_function(...).

See also FORBID_CALL(...) which creates an expectation that is valid until the end of the surrounding scope.

NAMED_REQUIRE_CALL( mock_object, func_name(parameter_list))

Make a std::unique_ptr<trompeloeil::expectation> requiring that mock_obj.func_name(parameter_list) is called exactly once before the expectation object is destroyed. parameter_list may contain exact values or matchers that describes matching calls.

The number of matches required before the expectation object is destroyed can be changed with an optional TIMES(...) clause.

NOTE! Any named objects referenced in attached LR_WITH(...), LR_SIDE_EFFECT(...), LR_RETURN(...) and LR_THROW(...) are captured by reference so lifetime management is important.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
}

using trompeloeil::gt;
using trompeloeil::lt;

using expectation = std::unique_ptr<trompeloeil::expectation>;

TEST(atest)
{
  C mock_obj;

  expectation x1 = NAMED_REQUIRE_CALL(mock_obj, func(gt(0));

  test_function(0, &mock_obj);

  expectation x2 = NAMED_REQUIRE_CALL(mock_obj, func(lt(0));

  test_function(1, &mock_obj);

  x1.reset(); // The call with positive number must be done here.

  test_function(2, &mock_obj);
}

Above, the first two calls to test_function(...) must together call mock_obj.func(...) exactly once with a positive value, and the last two calls to test_function(...) must together call mock_obj.func(...) exactly once with a negative number.

See also REQUIRE_CALL(...) which creates an expectation that is valid until the end of the surrounding scope.

NAMED_REQUIRE_DESTRUCTION( mock_object )

Create a std::unique_ptr<trompeloeil::expectation> object which reports a violation if the deathwatched_type mock object is not destroyed by the time the expectation is destroyed.

#include <trompeloeil/lifetime.hpp>

Example:

class C
{
public:
  virtual ~C() = default; // must be virtual for deathwatched
  MAKE_MOCK1(func, void(int));
}

using monitor = std::unique_ptr<trompeloeil::expectation>;
using trompeloeil::deathwatched;

TEST(atest)
{
  C* p = new deathwatched<C>();

  test_function(0, p); // must not destroy *p

  monitor m = NAMED_REQUIRE_DESTRUCTION(*p);

  test_function(1, p);

  m.reset(); // *p must have been destroyed here
}

Above, p points to a deathwatched mock object, meaning that a violation is reported if *p is destroyed without having a destruction requirement.

The monitor m is a requirement that *p is destroyed before the lifetime_monitor (subtype of expectation) held by m is destroyed.

It is thus a violation if the first call to test_function(...) destroys *p, and another violation if the second call to test_function(...) does not destroy *p

See also REQUIRE_DESTRUCTION(...) which places a requirement that the deathwatched mock object is destroyed before the end of the scope.

REQUIRE_CALL( mock_object, func_name(parameter_list))

Make an expectation requiring that mock_obj.func_name(parameter_list) is called exactly once before the end of the scope. parameter_list may contain exact values or matchers that describes matching parameter values for the expectation.

The number of matches required before the expectation object is destroyed can be changed with an optional TIMES(...) clause.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(int));
}

using trompeloeil::gt;
using trompeloeil::lt;

TEST(atest)
{
  C mock_obj;
  {
    REQUIRE_CALL(mock_obj, func(gt(0));

    test_function(0, &mock_obj);
    // end of scope, requirement must be fulfilled here
  }
  {
    REQUIRE_CALL(mock_obj, func(lt(0));

    test_function(1, &mock_obj);
    // end of scope, requirement must be fulfilled here
  }
}

Above, the first call to test_function(...) must call mock_obj.func(...) exactly once with a positive value, and the second call to test_function(...) must call mock_obj.func(...) exactly once with a negative number.

See also NAMED_REQUIRE_CALL(...) which creates an expectation that is held by a std::unique_ptr<trompeloeil::expectation> which can be stored in test fixtures.

REQUIRE_DESTRUCTION( mock_object )

Create an anonymous lifetime_monitor which reports a violation if the deathwatched mock object is not destroyed by the end of the scope.

#include <trompeloeil/lifetime.hpp>

Example:

class C
{
public:
  virtual ~C() = default; // must be virtual for deathwatched
  MAKE_MOCK1(func, void(int));
}

using trompeloeil::deathwatched;

TEST(atest)
{
  C* p = new deathwatched<C>();

  test_function(0, p); // must not destroy *p

  {
    REQUIRE_DESTRUCTION(*p);

    test_function(1, p);
    // end of scope, *p must have been destroyed here
  }
}

Above, p points to a deathwatched mock object, meaning that a violation is reported if *p is destroyed without having a destruction requirement.

REQUIRE_DESTRUCTION(...) in the local scope puts a requirement on *p that it must be destroyed by the end of the scope.

It is thus a violation if the first call to test_function(...) destroys *p, and another violation if the second call to test_function(...) does not destroy *p.

See also NAMED_REQUIRE_DESTRUCTION(...) which creates the requirement that the deathwatched mock object is destroyed as a std::unique_ptr<trompeloeil::lifetime_monitor> which can be stored in test fixtures.

RETURN( expr )

Used in expectations to set the return value after having evaluated every SIDE_EFFECT(...) and LR_SIDE_EFFECT(...). For void functions RETURN(...) is illegal. For non-void functions exactly one of LR_RETURN(...), RETURN(...), LR_THROW(...) or THROW(...) is required. expr may refer to parameters in the call with their positional names _1, _2, etc. This code may alter out-parameters.

Named local objects accessed here refers to a immutable copies.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, int&(unsigned));
};

using trompeloeil::_;

std::vector<int> values{3,2,1,0};

TEST(atest)
{
  C mock_obj;

  int offset = 1;
  ALLOW_CALL(mock_obj, func(_))
    .WITH(_1 + offset < values.size())
    .RETURN(values[_1 + offset]);

  offset = 2;
  test_func(&mock_obj);
}

Above, the RETURN(...) clause tells matching calls of mock_obj.func(...) to return a reference to an element in the global std::vector<int> values. Since RETURN(...) accesses copies of local variables, the value of offset is 1 in the index calculation if called from within test_func(...).

NOTE! It is illegal to return a reference to a captured local variable.

See also LR_RETURN(...) which accesses local variables by reference.

SIDE_EFFECT( expr )

Used in expectations to cause side effects for matching calls. expr is only evaluated when all WITH(...) and LR_WITH(...) clauses are matched. expr may refer to parameters in the call with their positional names _1, _2, etc. This code may alter out-parameters. Several SIDE_EFFECT(...) and LR_SIDE_EFFECT(...) clauses can be added to a single expectation, and they are evaluated in order.

Named local objects accessed here refers to immutable copies.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(unsigned));
};

unsigned sum = 0;

TEST(atest)
{
  C mock_obj;
  unsigned offset = 0;
  ALLOW_CALL(mock_obj, func(ANY(unsigned))
    .SIDE_EFFECT(sum += offset + _1);

  offset = 2;
  tested_func(&mock_obj);

  std::cout << "offset corrected parameter sum=" << sum << "\n";
}

Above, tested_func(...) is allowed to call mock_obj.func() any number of times. Each time a side effect is that the global variable sum gets the parameter value added to it adjusted for offset. Since SIDE_EFFECT(...) refers to a copy of offset, the value of offset is 0 in any matching calls from within tested_func(...)

See also LR_SIDE_EFFECT(...) which accesses local objects by reference.

THROW( expr )

Used in expectations to throw after having evaluated every SIDE_EFFECT(...) and LR_SIDE_EFFECT(...) for a matching call. expr may refer to parameters in the call with their positional names _1, _2, etc. This code may alter out-parameters. It is not legal to combine THROW(...) with any of LR_THROW(...), LR_RETURN(...) or RETURN(...).

Named local objects here refers to immutable copies.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(unsigned));
};

TEST(atest)
{
  C mock_obj;
  std::string what="<unknown>";

  ALLOW_CALL(mock_obj, func(3))
    .THROW(std::invalid_argument(what));

  what = "";
  tested_func(&mock_obj);
}

Above, THROW(...) will refer to a copy of the string what with the value "<unknown>" if a matching call is made from within tested_func(...)

See also LR_THROW(...) which accesses copies of local objects.

TIMES( limits ) and RT_TIMES( limits )

Used in REQUIRE_CALL(...) and NAMED_REQUIRE_CALL(...) to set the limits on the number of matching calls required.

limits may be a single number, in which case it is the exact number of matching calls required.

limits may also be two numbers, describing a range min-inclusive, max-inclusive.

If the minimum number of matching calls is not met before the end of the lifetime of the expectation, a violation is reported.

If the maximum number of matching calls is exceeded, a violation is reported.

The difference between TIMES(...) and RT_TIMES(...) is, that the prior only supports constexpr arguments, while the latter is designed to accept also runtime arguements. If invalid bounds are provided, TIMES(...) issues a compile-error. RT_TIMES(...) will compile successfully, but will raise a std::logic_error during construction.

Either a single TIMES(...) or RT_TIMES(...) may be used for each REQUIRE_CALL(..) or NAMED_REQUIRE_CALL(...).

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(unsigned));
};

using trompeloeil::_;

TEST(atest)
{
  C mock_obj;

  REQUIRE_CALL(mock_obj, func(_))
    .TIMES(2, 5);

  tested_func(&mock_obj);

Above, tested_func(...) is expected to call mock_obj.func() at least two times, and no more than 5 times.

See also the helpers AT_LEAST(...) and AT_MOST(...).

See also IN_SEQUENCE(...) for information about how .TIMES(...) and .RT_TIMES(...) work together with sequence objects.

WITH( expr )

Used with expectations to add further conditions for a matching call. Typically used when matchers are used for the parameters, and often when the condition requires several parameter values together. expr can refer to parameters in the call with their positional names _1, _2, etc. Even if the function signature has parameters as non-const references, they are immutable in this context. Several WITH(...) and LR_WITH(...) clauses can be added to a single expectation and they are tried in the order until one has failed, or they all have passed.

Named local objects here refers to immutable copies.

#include <trompeloeil/mock.hpp>

Example:

class C
{
public:
  MAKE_MOCK1(func, void(const char*, size_t));
};

using trompeloeil::_;

TEST(atest)
{
  C mock_obj;

  std::string str = "string";

  REQUIRE_CALL(mock_obj, func(_,_))
    .WITH(std::string(_1, _2) == str);

  str = ""; // does not alter the copy in the expectation above.

  tested_func(buff, &mock_obj);
}

Above, WITH(std::string(_1, _2) == str) checks the condition that the string constructed from the parameters is equal to a copy of the local variable str. To pass the test, tested_func(...) must in other words call mock_obj.func() with string "string".

NOTE! It is legal, but a very bad idea, to modify global/static objects in WITH(...). If several expectations could match and are disambiguated by LR_WITH(...) and WITH(...) the global/static objects will be modified also by those expectations that do not match.

See also LR_WITH(...) which accesses local objects by reference.

Types and Templates (alphabetical order)

trompeloeil::deathwatched<T>

Template used when it is necessary to control the life time of a mock object. The macros REQUIRE_DESTRUCTION(...) and NAMED_REQUIRE_DESTRUCTION(...) operates on instances of trompeloeil::deathwatched<T>.

#include <trompeloeil/lifetime.hpp>

Example:

class Mock
{
public:
  virtual ~Mock() = default; // virtual destructor needed for deathwatched<>
  MAKE_MOCK1(func, void(int));
};

using trompeloeil::_;

void test_func()
{
  auto p = new trompeloeil::deathwatched<Mock>();
  ALLOW_CALL(*p, func(_));
  func1(p);
  {
    FORBID_CALL(*p, func(_));
    REQUIRE_DESTRUCTION(*p);
    func2(p);
  }
}

Above, func1(p) must not destroy p, or a violation is reported, and func2(p) may not call the mock function on p, but is required to destroy the mock object, or a violation will be reported.

trompeloeil::deathwatched<T> inherits from T, and the constructor accepts any parameters and perfectly forwards them to the constructor of T. The mock type T must have a virtual destructor.

trompeloeil::expectation

Base class for all expectations. The macros NAMED_ALLOW_CALL(...), NAMED_FORBID_CALL(...) and NAMED_REQUIRE_CALL(...) results in a std::unique_ptr<trompeloeil::expectation> which you can hold in a variable.

#include <trompeloeil/mock.hpp>

trompeloeil::expectation_violation

The exception type used by default to report violations.

class expectation_violation : public std::logic_error
{
public:
  using std::logic_error::logic_error;
};

The what() string contains the violation report message.

#include <trompeloeil/mock.hpp>

trompeloeil::lifetime_monitor

The macro NAMED_REQUIRE_DESTRUCTION(...) results in a std::unique_ptr<trompeloeil::lifetime_monitor> which you can hold in a variable. trompeloeil::lifetime_monitor inherits from trompeloeil::expectation.

#include <trompeloeil/lifetime.hpp>

Example:

class Mock
{
public:
  virtual ~Mock() = default; // virtual destructor needed for deathwatched<>
  MAKE_MOCK1(func, void(int));
};

using trompeloeil::_;
using monitor = std::unique_ptr<trompeloeil::lifetime_monitor>;

void test_func()
{
  auto p = new trompeloeil::deathwatched<Mock>();
  ALLOW_CALL(*p, func(_));
  func1(p);
  {
    FORBID_CALL(*p, func(_));
    monitor m = NAMED_REQUIRE_DESTRUCTION(*p);
    std::unique_ptr<trompeloeil::expectation> e = std::move(m);
    func2(p);
    e.reset();
  }
}

trompeloeil::matcher

trompeloeil::matcher is the base class for all matchers. It does not do anything and is solely used in internal SFINAE constructions and tag dispatch

Use it, or trompeloeil::typed_matcher<T>, as the base class when writing custom matchers.

#include <trompeloeil/mock.hpp>

trompeloeil::mock_interface<T>

trompeloeil::mock_interface<T> is a template useful when creating a mock from an existing interface (i.e. a struct or class with virtual functions that you want to mock).

It enables use of the IMPLEMENT_MOCKn(...) and IMPLEMENT_CONST_MOCKn(...) macros. The MAKE_MOCK(...), MAKE_MOCKn(...), MAKE_CONST_MOCK(...) and MAKE_CONST_MOCKn(...) macros can also be used.

The interface type T must not be final.

#include <trompeloeil/mock.hpp>

Example:

class interface
{
public:
  virtual ~interface() = default;
  virtual void func(int) = 0;
};

class mock : trompeloeil::mock_interface<interface>
{
public:
  IMPLEMENT_MOCK1(func); // implements pure virtual interface::func(int);
};

void tested_func(interface& i);

void test()
{
  mock m;
  REQUIRE_CALL(m, func(3));
  tested_func(m);
}

NOTE! mock_interface<T> cannot be used to inherit multiple interfaces.

trompeloeil::ok_reporter_func

A type used to pass information to the unit testing frame work that a call to a mock function has not been reported as a violation.

using trompeloeil::ok_reporter_func = std::function<const char*>;

#include <trompeloeil/mock.hpp>

The string passed is the parameters to the expectation. E.g.

struct Mock
{
  MAKE_MOCK1(func, void(int));
};

TEST(...)
{
  Mock m;
  REQUIRE_CALL(m, func(3)); // passes "m.func(3)" to OK reporter

  ...
}

trompeloeil::printer<T>

printer<T> is a type that formats values to strings in reports from Trompeloeil.

template <typename T, typename = void>
struct printer
{
  static void print(ostream& os, const T& t);
};

By default the print function formats using os << t, provided the type T can be inserted into an ostream, otherwise it gives a hex-dump of the bytes occupied by the object.

The type trompeloeil::printer<T> is a customization point that you can use to define string formatting for types that do not support os << t, or for which you want a different representation in reports from Trompeloeil. The second template parameter, which must be void if present, is a chance to add SFINAE constraints on the T. See example in the Cook Book.

#include <trompeloeil/mock.hpp>

trompeloeil::reporter_func

A type used to pass information to the unit testing frame work that a call has been made in violation of a mock function.

using trompeloeil::reporter_func = std::function<void(trompeloeil::severity,
                                                      char const *file,
                                                      unsigned long line,
                                                      const std::string& msg)>;

See trompeloeil::severity.

The parameter msg contains detailed information about the violation and which (if any) expectations there are on the mock function.

#include <trompeloeil/mock.hpp>

trompeloeil::sequence

Type of object used for fine-tuned control of sequencing of matched expectations.

#include <trompeloeil/sequence.hpp>

Example:

class FileOps
{
public:
  using handle = int;
  MAKE_MOCK1(open, handle(const std::string&));
  MAKE_MOCK3(write, size_t(handle, const char*, size_t));
  MAKE_MOCK1(close, void(handle));
};

using trompeloeil::ne;

void test()
{
  FileOps ops;

  auto seq = trompeloeil::sequence; // sequence object

  int handle = 4711;

  REQUIRE_CALL(ops, open("name"))
    .RETURN(handle)
    .IN_SEQUENCE(seq);

  REQUIRE_CALL(ops, write(handle, ne(nullptr), ne(0)))
    .RETURN(0)                                         // indicate failure
    .IN_SEQUENCE(seq);

  REQUIRE_CALL(ops, write(handle, ne(nullptr), ne(0)))
    .RETURN(_3)                                        // successful retry
    .IN_SEQUENCE(seq);

  REQUIRE_CALL(ops, close(handle))
    .IN_SEQUENCE(seq);

  test_writes(&ops);
}

Sequence objects are movable but not copyable.

NOTE! The .IN_SEQUENCE(...) macro accepts many sequence objects.

trompeloeil::severity

Type used in violation reports to dictate what actions are allowed by the report handler.

namespace trompeloeil {
  enum class severity { fatal, nonfatal };
}

A value of trompeloeil::severity::fatal dictates that the report handler must not return. It may throw or end the program execution.

A value of trompeloeil::severity::nonfatal dictates that the report handler is called from stack rollback and must not throw, lest std::terminate is called.

#include <trompeloeil/mock.hpp>

trompeloeil::stream_tracer

An instance of trompeloeil::stream_tracer prints information about matched calls to the output stream it refers to. stream_tracer inherits from trompeloeil::tracer.

#include <trompeloeil/stream_tracer.hpp>

namespace trompeloeil {
class stream_tracer : public ::trompeloeil::tracer
{
public:
  stream_tracer(std::ostream& stream);
  void trace(char const* file, unsigned long line, std::string const& call) override;
};
}

See "Using trompeloeil::stream_tracer" in the Cook Book.

trompeloeil::tracer

Base class for tracers. Inherit from it when writing custom tracers.

#include <trompeloeil/stream_tracer.hpp>

namespace trompeloeil {
class tracer
{
public:
  virtual void trace(char const* file, unsigned long line, std::string const& call) = 0;
protected:
   tracer();
   tracer(tracer const&) = delete;
   virtual ~tracer();
   ...
};
}

See "Writing custom tracers" in the Cook Book for an example.

trompeloeil::typed_matcher<T>

Convenience class available when writing custom matchers for a specific type. It inherits from trompeloeil::matcher.

See "Writing custom matchers" in the Cook Book for examples.

#include <trompeloeil/matcher.hpp>

Functions

trompeloeil::expectation::is_satisfied() const

Query an expectation object if it is satisfied, i.e. if it will not report a missing call if it is destroyed. If .TIMES() is used, this is true if the minimum number of calls has been reached.

#include <trompeloeil/mock.hpp>

test(...)
{
  ...
  auto e = NAMED_REQUIRE_CALL(mock_obj, func())
             .TIMES(2,5);
  assert(!e->is_satisfied()); // no calls made yet.
  mock_obj.func();
  assert(!e->is_satisfied()); // Only one call made, min is 2.
  mock_obj.func();
  assert(e->is_satisfied()); // now 2 calls are made, so it's satisfied
  mock_obj.func();
  assert(e->is_satisfied()); // 3 calls are made, it's still satisfied
}

trompeloeil::expectation::is_saturated() const

Query an expectation object if it is saturated, i.e. if another call will report an unexpected call. If .TIMES() is used, this is true if the maximum number of calls has been reached.

#include <trompeloeil/mock.hpp>

  ...
  auto e = NAMED_REQUIRE_CALL(mock_obj, func())
             .TIMES(2,4);
  assert(!e->is_saturated()); // no calls made yet.
  mock_obj.func();
  assert(!e->is_saturated()); // Only one call made, max is 4.
  mock_obj.func();
  assert(!e->is_saturated()); // now 2 calls are made, still not saturated
  mock_obj.func();
  assert(!e->is_saturated()); // 3 calls, one more to go.
  mock_obj.func();
  assert(e->is_saturated());  // 4 calls, the expectation is now saturated

  /* mock_obj.func();*/ // would cause "unexpected call" error.

trompeloeil::get_lock()

Get the global recursive_mutex used by Trompeloeil. The mutex is held until the end of the scope.

#include <trompeloeil/mock.hpp>

trompeloeil::print(std::ostream& os, T const& t)

By default print() uses the type printer<T> to format data to strings.

You can write specializations of trompeloeil::print(std::ostream& os, T const& t) for your own types T, but it is preferable to write a specialization of the type printer<T> instead, which also works for partial specializations. See example in the Cook Book.

#include <trompeloeil/mock.hpp>

trompeloeil::is_null(T const&)

Null check that works for all types. If T is not comparable with nullptr the value is false. This is mostly used when writing duck typed matchers.

#include <trompeloeil/mock.hpp>

trompeloeil::make_matcher<Type>(...)

template <typename Type, typename Predicate, typename Printer, typename ... T>
auto make_matcher(Predicate predicate /* bool (Type& value, T const& ...) */,
                  Printer printer     /* void (std::ostream&, T const& ...) */,
                  T&& ... stored_values);

If Type is trompeloeil::wildcard a duck typed matcher is created, otherwise a matcher for the specified type Type is created.

T&&... is any number of values you want stored in the matcher.

predicate is a callable object, typically a lambda, that accepts the value to check for, and each of the stored values T&&... in order as const&. When Type is trompeloeil::wildcard, the first parameter must be of auto type. The return value must be convertible to bool.

printer is a callable object, typically a lambda, that accepts an ostream& and the stored values T&&... in order as const&.

Examples are found in the Cook Book under Writing custom matchers

#include <trompeloeil/matcher.hpp>

trompeloeil::set_reporter(...)

These functions are used to adapt Trompeloeil to your unit test framework of choice.

The default reporter throws trompeloeil::expectation_violation for all reports, with the violation message in the what() string.

If this is not suitable, you can change the report mechanism by calling trompeloeil::set_reporter(...)

#include <trompeloeil/mock.hpp>

reporter_func
trompeloeil::set_reporter(std::function<void(trompeloeil::severity,
                                             char const *file,
                                             unsigned long line,
                                             const std::string& msg)>)

The return value is the previous reporter function.

std::pair<reporter_func, ok_reporter_func>
trompeloeil::set_reporter(std::function<void(trompeloeil::severity,
                                             char const *file,
                                             unsigned long line,
                                             const std::string& msg)> reporter,
                          std::function<void(char const* msg> ok_reporter)
)

The return value is the previous reporter and ok_reporter. An ok_reporter is called for every call to a mock function that is not reported as a violation. By default OK reports are ignored.

See trompeloeil::severity for the rules that it dictates.

See trompeloeil::reporter_func and trompeloeil::ok_reporter_func for details.

The Cook Book lists adapter code for a number of popular unit test frame works.

bool trompeloeil::sequence::is_completed() const

Member function of sequence object, used to query if the sequence it describes is completed or not.

#include <trompeloeil/sequence.hpp>

Example:

void test()
{
  auto seq = trompeloeil::sequence;
  mock_type mock;
  REQUIRE_CALL(mock, func1())
    .IN_SEQUENCE(seq);
  REQUIRE_CALL(mock, func2())
    .TIMES(100)
    .IN_SEQUENCE(seq);
  assert(!seq.is_completed()); // no calls yet
  mock.func1();
  assert(!seq.is_completed()); // only first call, one remaining
  mock.func2();
  assert(seq.is_completed());  // now sequence is completed
}

Constants

trompeloeil_movable_mock

By adding a static constexpr bool member trompeloeil_movable_mock with the value true to your mock struct/class, you make it move constructible. Note that when a mock object is moved, any current expectations will be taken over by the newly constructed mock object, but note also that if the implicitly created lambdas associated with .WITH(), .SIDE_EFFECT(), .RETURN() and .THROW() and their LR_ counter parts, refers to member variables in the mock objects, they will continue to refer the old moved from object.

#include <trompeloeil/mock.hpp>

class immobile
{
public:
  MAKE_MOCK1(func, void(int));
};

class movable
{
public:
  int i = 0;

  static constexpr bool trompeloeil_movable_mock = true;
  // allow move construction

  MAKE_MOCK1(func, void(int));
};

template <typename T>
T transfer(T t)
{
  return t;
}

test(...)
{
  auto m = transfer(immobile{}); // compilation error
  ...
}
test(...)
{
  movable m;
  auto e = NAMED_REQUIRE_CALL(m, func(3));
  auto mm = transfer(std::move(m));
   // A call to mm.func() now satisfies e
  ...
}
test(...)
{
  movable m{3};
  auto e = NAMED_REQUIRE_CALL(m, func(_))
    .LR_WITH(_1 == m.i);
  auto mm = transfer(std::move(m)); // Danger! e still refers to m.i.
  ...
}

Also, keep in mind the lifetime of expectations. If the lifetime of an expectation is associated with the life of the moved-from object, your test will likely fail, since the expectation object would then be destroyed before it has been satisfied. Example:

class movable
{
public:
  static constexpr bool trompeloeil_movable_mock = true;

  MAKE_MOCK0(func, void());
};

movable setup()
{
  movable obj;
  REQUIRE_CALL(obj, func());
  return obj;
  // Expectation dies here, unsatisfied, failing the test
}

test(...)
{
  movable obj = setup(); // test fails when returning from setup()
  ...
}

Using NAMED_REQUIRE_CALL(), NAMED_ALLOW_CALL() or NAMED_FORBID_CALL() can help, since they make the expectation life times more visible.