Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic custom action to set value to void** argument using gmock

I have been test-driving some code that uses COM interfaces using gmock. Win32 functions for working with COM return interface pointers via void ** arguments. When mocking a call to, for example, QueryInterface function that will return a pointer to IPersistFile interface, I do the following

CPersistFileMock mockIPersistFile;
EXPECT_CALL(mockIShellLink, QueryInterface(_, _)).WillOnce(DoAll(
    SetArg1ToIPersistFile(&mockIPersistFile), Return(S_OK)));

where SetArg1ToIPersistFile is a custom action defined like this:

ACTION_P(SetArg1ToIPersistFile, pIPersistFile) {
    *reinterpret_cast<CPersistFileMock**>(arg1) = pIPersistFile;
}

This works, but the problem is that you have to write a new custom action for every combination of argument index and the type that need to be returned via void ** argument. Is there a way to generalize this custom action so it can be applied regardless of type and argument index (to something like SetArgPointee<>but also aware of types).

like image 631
Marko Popovic Avatar asked Mar 21 '26 05:03

Marko Popovic


1 Answers

This question has been bothering our team, we knew that we could exploit the the fact that args is a tuple by using std::get<> on it but we did not know how to pass argument index and type in a generic way. Finally, a colleague of mine figured out how to make action template. This is the final implementation:

ACTION_TEMPLATE(SetArgVoidPtrPtr, HAS_2_TEMPLATE_PARAMS(typename, Type, unsigned, uIndex), AND_1_VALUE_PARAMS(value))
{
    *reinterpret_cast<Type**>(std::get<uIndex>(args)) = value;
}

and how it's use in context of IFilePersist example mentioned above:

EXPECT_CALL(mockIShellLink, QueryInterface(_, _)).WillOnce(DoAll(
    SetArgVoidPtrPtr<CPersistFileMock, 1>(&mockIPersistFile), Return(S_OK)));

Note that this approach can be used in general case, with functions that return values via void ** arguments. Just wanted to put this out there, since I did not find much information about this. Hope this helps someone with a similar problem.

like image 57
Marko Popovic Avatar answered Mar 23 '26 19:03

Marko Popovic



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!