Skip to content

Commit

Permalink
Merge pull request #33 from smalti/32-add-macro-expansion-support-for…
Browse files Browse the repository at this point in the history
…-win32-when-using-restore_module_func-verify_and_clear_module_func_expectations

Added macro expansion support
  • Loading branch information
smalti authored Jan 25, 2024
2 parents a6fdce4 + 22a19c8 commit f0cddc8
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 22 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,14 @@ ON_MODULE_FUNC_CALL(GetCurrentProcessId).WillByDefault(Return(42));
ON_MODULE_FUNC_CALL(GetProcessIdOfThread, Eq(HANDLE(42))).WillByDefault(Return(1));
```

#### 4. To validate and clear expectations after tests use the `VERIFY_AND_CLEAR_MODULE_FUNC_EXPECTATIONS` macro (usually used for multiple tests with different expectations and can be executed as part of the test tear-down logic)
#### 4. To validate and clear expectations after tests use the `VERIFY_AND_CLEAR_MODULE_FUNC` or `VERIFY_AND_CLEAR_MODULE_FUNC_EXPECTATIONS` macro (usually used for multiple tests with different expectations and can be executed as part of the test tear-down logic)

```cpp
// Verifies and removes the expectations
VERIFY_AND_CLEAR_MODULE_FUNC_EXPECTATIONS(GetCurrentProcessId);

// Verifies and removes the expectations and removes the default actions set by ON_CALL
VERIFY_AND_CLEAR_MODULE_FUNC(GetProcessIdOfThread);
```
#### 5. Use the `RESTORE_MODULE_FUNC` macro to restore the original module function and remove the IAT patch after all tests finished
Expand Down Expand Up @@ -130,7 +134,8 @@ After mock expectations set:
GetCurrentProcessId: 42
GetProcessIdOfThread: 1
```
Here are some additional examples of library usage: [gmock-win32-sample](https://github.com/smalti/gmock-win32-sample)

### Here are some additional examples of library usage: [gmock-win32-sample](https://github.com/smalti/gmock-win32-sample)

# Advanced Topics

Expand Down
62 changes: 42 additions & 20 deletions include/gmock-win32.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,15 @@ namespace detail {
void patch_module_func (const char*, void*, void*, void**);
void restore_module_func (const char*, void*, void*, void**);

template< typename TFunc, typename TStub >
void patch_module_func_non_optimized(
const char* func_name, void** old_fn, TFunc func, TStub stub)
{
if (!(*old_fn))
patch_module_func(
func_name, func, reinterpret_cast< void* >(stub), old_fn);
}

} // namespace detail
} // namespace gmock_win32

Expand Down Expand Up @@ -937,7 +946,8 @@ struct mock_module_##func : \
#define MOCK_MODULE_AVOID_OPT_(m) \
__pragma(optimize("", on)) \
static void patch_module_func_##m() { \
::patch_module_func_(#m, mock_module_##m::pp_old_fn(), &::m, &mock_module_##m::stub); \
gmock_win32::detail::patch_module_func_non_optimized( \
#m, mock_module_##m::pp_old_fn(), &::m, &mock_module_##m::stub); \
} \
__pragma(optimize("", off))

Expand All @@ -953,22 +963,7 @@ struct mock_module_##func : \
MOCK_MODULE_OVERLOAD_( MOCK_MODULE_NBARG_(__VA_ARGS__), _STDCALL_CONV, (m, r(__VA_ARGS__)) ) \
MOCK_MODULE_AVOID_OPT_( m )

// Hidden from optimizer
template< typename TFunc, typename TStub >
void patch_module_func_(const char* func_name, void** old_fn, TFunc func, TStub stub) {
if (!(*old_fn))
gmock_win32::detail::patch_module_func(
func_name, func, reinterpret_cast< void* >(stub), old_fn);
}

#define MODULE_FUNC_CALL_EXPANDED_(EXPECTATION_, func, ...) \
MODULE_FUNC_CALL_IMPL_(EXPECTATION_, func, __VA_ARGS__)

#define EXPECT_MODULE_FUNC_CALL(func, ...) \
MODULE_FUNC_CALL_EXPANDED_(EXPECT_CALL, func, __VA_ARGS__)

#define ON_MODULE_FUNC_CALL(func, ...) \
MODULE_FUNC_CALL_EXPANDED_(ON_CALL, func, __VA_ARGS__)
// Expectations

#define MODULE_FUNC_CALL_IMPL_(EXPECTATION_, func, ...) \
patch_module_func_##func(); \
Expand All @@ -977,15 +972,42 @@ void patch_module_func_(const char* func_name, void** old_fn, TFunc func, TStub
func(__VA_ARGS__)))& >(gmock_win32::detail::make_proxy( \
EXPECTATION_(mock_module_##func::instance(), func(__VA_ARGS__))))

#define REAL_MODULE_FUNC(func) \
#define EXPECT_MODULE_FUNC_CALL(func, ...) \
MODULE_FUNC_CALL_IMPL_(EXPECT_CALL, func, __VA_ARGS__)

#define ON_MODULE_FUNC_CALL(func, ...) \
MODULE_FUNC_CALL_IMPL_(ON_CALL, func, __VA_ARGS__)

// Real function call

#define REAL_MODULE_FUNC_IMPL_(func) \
reinterpret_cast< decltype(&func) >(*mock_module_##func::pp_old_fn())

#define REAL_MODULE_FUNC(func) \
REAL_MODULE_FUNC_IMPL_(func)

#define INVOKE_REAL_MODULE_FUNC(func, ...) \
REAL_MODULE_FUNC(func)(__VA_ARGS__)

// Verifying and removing expectations

#define VERIFY_AND_CLEAR_MODULE_FUNC_IMPL_(func) \
::testing::Mock::VerifyAndClear(&mock_module_##func::instance())

#define VERIFY_AND_CLEAR_MODULE_FUNC(func) \
VERIFY_AND_CLEAR_MODULE_FUNC_IMPL_(func)

#define VERIFY_AND_CLEAR_MODULE_FUNC_EXPECTATIONS_IMPL_(func) \
::testing::Mock::VerifyAndClearExpectations(&mock_module_##func::instance())

#define VERIFY_AND_CLEAR_MODULE_FUNC_EXPECTATIONS(func) \
::testing::Mock::VerifyAndClearExpectations(&mock_module_##func::instance());
VERIFY_AND_CLEAR_MODULE_FUNC_EXPECTATIONS_IMPL_(func)

#define RESTORE_MODULE_FUNC(func) \
// Functions restoring

#define RESTORE_MODULE_FUNC_IMPL_(func) \
gmock_win32::detail::restore_module_func( \
#func, *mock_module_##func::pp_old_fn(), mock_module_##func::stub, mock_module_##func::pp_old_fn())

#define RESTORE_MODULE_FUNC(func) \
RESTORE_MODULE_FUNC_IMPL_(func)
1 change: 1 addition & 0 deletions src/gmock-win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ namespace utils {
{
std::shared_ptr< void > finalAction(nullptr, [&](auto&&...)
{
// Ignore all function failures
core->pfn_FlushInstructionCache(processHandle, address, size);
core->pfn_VirtualProtect(address, size, oldProtect, &oldProtect);
});
Expand Down

0 comments on commit f0cddc8

Please sign in to comment.