Skip to content

Commit

Permalink
Merge branch 'rollbear:main' into feature/DYN_TIMES
Browse files Browse the repository at this point in the history
  • Loading branch information
DNKpp authored Sep 26, 2024
2 parents 99aecb5 + 746ea0e commit 5b64402
Show file tree
Hide file tree
Showing 15 changed files with 1,083 additions and 578 deletions.
961 changes: 486 additions & 475 deletions .github/workflows/ci.yml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ option(TROMPELOEIL_BUILD_TESTS "Build self test programs" off)

write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/trompeloeil/trompeloeil-config-version.cmake"
VERSION 47
VERSION 48
COMPATIBILITY AnyNewerVersion
ARCH_INDEPENDENT)

Expand Down
33 changes: 33 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
* When an expectation is constrained by several .WITH() clauses, a
violation report will only include the first failed condition,
short cirquiting the login.

Example:

REQUIRE_CALL(obj, func(_))
.WITH(_1 != nullptr)
.WITH(*_1 == 0); // would be runtime crash on nullptr access

Thank you Örjan Gustavsson for the suggestion.

v48 2024-07-17

* Fixed memory leak when adding an action (.RETURN, .SIDE_EFFECT, etc)
throws. Thank you Dominic Koepke for the fix.

* Dropped older compilers from CI builds (gcc <= 6 and clang <= 7) since
GitHub actions now require node-20, and no build environment is
currently available that both supports node-20 and older compilers.

* Support for STDMETHOD functions for COM. Thank you Luis Andres Cesena
for the implementation, and Kevin Puetz for the discussions. This
adds new macros:

MAKE_STDMETHOD_MOCKn(...)
IMPLEMENT_STDMETHOD_MOCKn(...)

* Fixed issue with std::expected causing compilation error. Thank you
@subbota-a for reporting

* Silenced gcc -Weffc++ warnings. Thanks Sven Fischer for the report

v47 2024-01-01

* Coroutines are conditionally supported by the __cpp_impl_coroutine
Expand Down
27 changes: 24 additions & 3 deletions docs/CookBook.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- [Mocking non-virtual member functions](#mocking_non_virtual)
- [Mocking free functions](#mocking_free_functions)
- [Mocking functions which return a template](#mocking_return_template)
- [Mocking __stdcall functions](#mocking_stdcall)
- [Setting Expectations](#setting_expectations)
- [Matching exact values](#matching_exact_values)
- [Matching values with conditions](#matching_conditions)
Expand Down Expand Up @@ -251,13 +252,14 @@ All tests passed (2 assertions in 1 test case)

The easiest way to use *Trompeloeil* with *Catch2* is to
`#include <catch2/trompeloeil.hpp>` in your test .cpp files. Note that the
inclusion order is important. `<catch.hpp>` must be included before
`<catch/trompeloeil.hpp>`.
inclusion order is important. `<catch.hpp>` (Catch2 2.x) or
`<catch2/catch_test_macros.hpp>` (Catch2 3.x) must be included before
`<catch2/trompeloeil.hpp>`.

Like this:

```Cpp
#include <catch.hpp>
#include <catch2/catch_test_macros.hpp>
#include <catch2/trompeloeil.hpp>

TEST_CASE("...
Expand Down Expand Up @@ -929,6 +931,25 @@ struct M
};
```
### <A name="mocking_stdcall"/> Mocking STDMETHOD functions
Windows API functions and COM Interfaces are declared with the
[__stdcall](https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170)
calling convention when targeting a 32-bit build, which becomes part of the
signature of a method. If you have the need to mock this type of functions the
[**`MAKE_STDMETHOD_MOCKn(...)`**](reference.md/#MAKE_STDMETHOD_MOCKn) and
[**`IMPLEMENT_STDMETHOD_MOCKn(...)`**](reference.md/#IMPLEMENT_STDMETHOD_MOCKn)
macros are provided.
```Cpp
struct Mock_stdcall : public trompeloeil::mock_interface<IUnknown>
{
IMPLEMENT_STDMETHOD_MOCK0(AddRef);
IMPLEMENT_STDMETHOD_MOCK0(Release);
MAKE_STDMETHOD_MOCK2(QueryInterface, HRESULT(REFIID, void **), override);
}
```

## <A name="setting_expectations"/> Setting Expectations

It is with [expectations](reference.md/#expectation) you define the behaviour
Expand Down
99 changes: 99 additions & 0 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
- [**`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)
Expand All @@ -38,6 +39,7 @@
- [**`LR_WITH(`** *expr* **`)`**](#LR_WITH)
- [**`MAKE_CONST_MOCKn(`** *func_name*, *signature* **`)`**](#MAKE_CONST_MOCKn)
- [**`MAKE_MOCKn(`** *name*, *signature* **`)`**](#MAKE_MOCKn)
- [**`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)
Expand Down Expand Up @@ -1016,6 +1018,56 @@ 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...* **`)`**
Expand Down Expand Up @@ -1493,6 +1545,53 @@ you can call [mock functions](#mock_function) from those.
See also [**`MAKE_CONST_MOCKn(...)`**](#MAKE_CONST_MOCKn) for `const`
member functions.

<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_STDMETHO_MOCK2(func1, int(int, const std::vector<int>&), override);
MAKE_STDMETHO_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.

<A name="NAMED_ALLOW_CALL"/>

### **`NAMED_ALLOW_CALL(`** *mock_object*, *func_name*(*parameter_list*)**`)`**
Expand Down
6 changes: 3 additions & 3 deletions include/trompeloeil/coro.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ namespace trompeloeil
auto expr = new yield_expr<signature, E>(std::forward<E>(e));
m.matcher->yield_expressions->push_back(expr);
}
return {m.matcher};
return {std::move(m).matcher};
}
};

Expand Down Expand Up @@ -261,7 +261,7 @@ namespace trompeloeil
m.matcher->yield_expressions)
);
}
return {m.matcher};
return {std::move(m).matcher};
}
};

Expand Down Expand Up @@ -303,7 +303,7 @@ namespace trompeloeil
m.matcher->return_handler_obj.reset(new ret_handler(std::move(handler),
m.matcher->yield_expressions));
}
return {m.matcher};
return {std::move(m).matcher};
}
};

Expand Down
2 changes: 2 additions & 0 deletions include/trompeloeil/lifetime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ struct lifetime_monitor : public expectation
}
}

lifetime_monitor& operator=(lifetime_monitor const&) = delete;

void
notify()
noexcept
Expand Down
Loading

0 comments on commit 5b64402

Please sign in to comment.