Gmock - How to set mock function parameter value from an input parameter? - unit-testing

I am using Gmock in my project. I have the following mock function.
MOCK_METHOD2(helper,
bool(const std::string&, std::string*));
Goal is to set value of parameter 1 to parameter 2 for all mock calls.
I did the following.
std::string temp;
EXPECT_CALL(
MockObj,
helper(_,_))
.WillRepeatedly(
DoAll(SaveArg<0>(&temp), //Save first arg to temp
SetArgPointee<1>(temp), //assign it to second arg
Return(true)));
However I see that parameter 2 is set to the original value of tmp rather than the value saved. Is there any other way to solve this? I want to make this EXPECT_CALL dynamic rather than doing SetArgPointee<1>("testval").

Standard actions do not support what you need. You will need to write a custom matcher:
ACTION(AssignArg0ToArg1) {
*arg1 = arg0;
}
And you can then use it in combination with Return(true). More information on custom actions can be found at https://github.com/google/googlemock/blob/master/googlemock/docs/DesignDoc.md.

Related

How to ignore the first action in the gtest DoAll()

I declare a function
void MyFunction(const std::wstring& inParameter, std::wstring& outParamater);
The first parameter is a passed in parameter, the second one is the value out parameter, the value I want to get by the function will pass it out by outParameter.
Now I Gmock it
MOCK_METHOD2(MyFunction, void(const std::wstring&, std::wstring&));
However, when I use this mock function:
std::wstring firstStr = L"firstStr";
std::wstring test = L"test";
EXPECT_CALL(*myGmockInstance, MyFunction(firstStr, _)).Times(1).WillOnce(DoAll(firstStr, SetArgReferee<1>(test)));
It doesn't work.
I also tried
EXPECT_CALL(*myGmockInstance, MyFunction(_, _)).Times(1).WillOnce(DoAll(_, SetArgReferee<1>(test)));
or
EXPECT_CALL(*myGmockInstance, MyFunction(_, _)).Times(1).WillOnce(DoAll(firstStr, SetArgReferee<1>(test)));
or
EXPECT_CALL(*myGmockInstance, MyFunction(_, _)).Times(1).WillOnce(DoAll(SetArgReferee<0>(firstStr), SetArgReferee<1>(test)));
I understand that the inParameter is const, so I cannot use SetArgReferee for it. But how to set its value and at the same time I can set value for outParameter?
I think that the title of your question is quite misleading. From what I understand, you just want to assign some arbitrary value to your function's second argument (the output argument). This is how you can do it using Invoke:
using ::testing::_;
void assignStringToArg(const std::wstring&, std::wstring& outputStr,
const std::wstring expectedStr) {
outputStr = expectedStr;
}
class SomeMock {
public:
MOCK_METHOD2(MyFunction, void(const std::wstring&, std::wstring&));
};
TEST(xxx, yyy) {
SomeMock someMock;
std::wstring firstStr(L"aaabbbccc");
std::wstring secondStr(L"I should change upon MyFunction call ...");
std::wstring expectedSecondStr(L"xxxyyyzzz");
EXPECT_CALL(someMock, MyFunction(firstStr, _)).Times(1).WillOnce(Invoke(std::bind(
&assignStringToArg,
std::placeholders::_1,
std::placeholders::_2,
expectedSecondStr)));
someMock.MyFunction(firstStr, secondStr);
ASSERT_EQ(expectedSecondStr, secondStr);
}
Note that the function provided to Invoke must have the same signature as the function that you expect to be called (that's why I use bind). You can achieve the same result using google macro ACTION_P. I prefer to use Invoke only because it looks more clean to me.
Since your case is rather simple, you can also do it using SetArgReferee like you tried before:
EXPECT_CALL(someMock, MyFunction(firstStr, _)).Times(1).WillOnce(
SetArgReferee<1>(L"something"));
someMock.MyFunction(firstStr, secondStr);
ASSERT_EQ(L"something", secondStr);
I just see no point using DoAll if you only want to do one action. But ... if you really insist:
EXPECT_CALL(someMock, MyFunction(firstStr, _)).Times(1).WillOnce(
DoAll(SetArgReferee<1>(L"something1"), SetArgReferee<1>(L"something2")));
someMock.MyFunction(firstStr, secondStr);
ASSERT_EQ(L"something2", secondStr);
It is rather stupid example, because it set's the output variable to L"something1" and then immediately to L"something2".

How to get list of StaticMesh from path?

I am trying to get list of Staticmesh from the specific path and set the Staticmesh to RootComponent. Please help on this issues. Code is below;
TArray<UObject*> MeshAssets;
EngineUtils::FindOrLoadAssetsByPath(TEXT("/Game/StarterContent/Meshs/"), MeshAssets, EngineUtils::ATL_Regular);
StaticMeshComponent->SetStaticMesh(MeshAssets.GetData);
StaticMeshComponent->AttachTo(RootComponent);
The Error is
Error 2 error C3867: 'TArray::GetData': function call missing argument list; use '&TArray::GetData' to create a
pointer to member<
StaticMeshComponent->SetStaticMesh(MeshAssets.GetData);
You're calling a function without the ( ) and possible parameters.
StaticMeshComponent->SetStaticMesh( MeshAssets.GetData( ) );
should work depending on whether there also have to be any parameters.
Some problems with your code:
Your Array is of type UObject*, but you need objects with the type UStaticMesh* for your component. The SetStaticMesh-method does not UObject* as parameter.
You can only set one item from your array as the mesh of your component, e.g. MeshAssets[0].
GetData is a method, not a variable. You have to call MeshAssets.GetData() if you want to use it.
So, your code should look more like this:
TArray<UObject*> MeshAssets;
EngineUtils::FindOrLoadAssetsByPath(TEXT("/Game/StarterContent/Meshs/"), MeshAssets, EngineUtils::ATL_Regular);
for (auto asset : MeshAssets) {
UStaticMesh* mesh = Cast<UStaticMesh>(asset);
if (mesh != nullptr) {
// do something with the mesh, create a component with it, etc.
}
}

How to register member function with lua-function parameter using luabind?

I need to register a member function using luabind which is supposed to take a lua-function as parameter. For any normal function I would usually just do this:
int SomeLuaFunction(lua_State *l)
{
luaL_checkfunction(l,1);
int fc = luaL_ref(l,LUA_REGISTRYINDEX);
[...]
}
Luabind however uses the parameter list, so I'm unsure how to tell it I'm expecting a function:
void Lua_ALSound_CallOnStateChanged(lua_State *l,boost::shared_ptr<ALSound> pAl,<function-parameter?>)
{
[...]
}
lua_bind(luabind::class_<ALSound COMMA boost::shared_ptr<ALSound>>("ALSound")
.def("CallOnStateChanged",&Lua_ALSound_CallOnStateChanged)
);
(Only the relevant part of the code is shown here, lua_bind is using luabind::module)
lua-example of what I'm trying to accomplish:
local al = ALSound() -- I'm aware this wouldn't work since I haven't defined a constructor
al:CallOnStateChanged(function()
[...]
end)
Perhaps there is a way to add additional functions to an already registered class without luabind? Any suggestions would be appreciated.
If you want to be able to have a function that takes Lua objects as parameters, you should have the function take a luabind::object as a parameter. Then you can check to see if it's a function and call it if it is.

Pass method parameter to an action in googlemock

I use Gmock for a method call, that returns an element of the QList heightsFromCsvResult as out parameter. Here is the currently working code:
EXPECT_CALL(*_mockAttributeRepository, getGeometryHeightValues(_,_))
.WillOnce(DoAll(SetArgReferee<1>(heightsFromCsvResult.at(0)), Return(true)))
.WillOnce(DoAll(SetArgReferee<1>(heightsFromCsvResult.at(1)), Return(true)))
.WillOnce(DoAll(SetArgReferee<1>(heightsFromCsvResult.at(2)), Return(true)))
.WillOnce(DoAll(SetArgReferee<1>(heightsFromCsvResult.at(3)), Return(true)));
The first parameter lineNumber from
getGeometryHeightValues(int lineNumber, QPair<QString, QString>)
is the index for heightsFromCsvResult.at(lineNumber).
Now I try to use Gmock in a more generic way:
int* mockLineNumber = new int;
EXPECT_CALL(*_mockAttributeRepository, getGeometryHeightValues(_,_))
.Times(4)
.WillRepeatedly(DoAll(SaveArg<0>(mockLineNumber), SetArgReferee<1>(heightsFromCsvResult.at(*(mockLineNumber))), Return(true)));
But this code does not work, because mockLineNumber is never written by Gmock. But the EXPECT_CALL is satisfied.
Does anyone see the problem in the code?
Using a variable set with SaveArg within the same EXPECT_CALL does not seem to be working, what you could do instead is to go through a custom action that sets the second argument using argument 0 as index on the passed container.
ACTION_P(SetArg1WithValueFromPassedArgumentUsingArg0AsIndex, param)
{
arg1 = param.at(arg0);
}
int* mockLineNumber = new int;
EXPECT_CALL(*_mockAttributeRepository, getGeometryHeightValues(_,_))
.Times(4)
.WillRepeatedly(DoAll(SaveArg<0>(mockLineNumber), SetArg1WithValueFromPassedArgumentUsingArg0AsIndex(heightsFromCsvResult), Return(true)));
Unless you need mockLineNumber for something else you could remove that part.

Parameters with and without arguments in boost::program_options

I wrote a small app that uses boost::program_options for command-line parsing.
I'd like to have some options that set a value if the argument is present, and alternately prints the current value if the parameter is given but no argument is present. So "set-mode" would look like:
dc-ctl --brightness 15
and "get mode" would be:
dc-ctl --brightness
brightness=15
The problem is, I don't know how to handle the second case without catching this exception:
error: required parameter is missing in 'brightness'
Is there an easy way to avoid having it throw that error? It happens as soon as the arguments are parsed.
I got a partial solution from How to accept empty value in boost::program_options which suggests using the implicit_value method on those parameters that may or may not have arguments present.
So my call to initialize the "brightness" parameter looks like this:
("brightness,b", po::value<string>()->implicit_value(""),
I then iterate over the variable map and for any argument that's a string, I check if it's empty and if so I print the current value. That code looks like this:
// check if we're just printing a feature's current value
bool gotFeature = false;
for (po::variables_map::iterator iter = vm.begin(); iter != vm.end(); ++iter)
{
/// parameter has been given with no value
if (iter->second.value().type() == typeid(string))
if (iter->second.as<string>().empty())
{
gotFeature = true;
printFeatureValue(iter->first, camera);
}
}
// this is all we're supposed to do, time to exit
if (gotFeature)
{
cleanup(dc1394, camera, cameras);
return 0;
}
UPDATE: this changes the aforementioned syntax, when using implicit values, now arguments, when given, must be of the form:
./dc-ctl -b500
instead of
./dc-ctl -b 500
Hope this is helpful to someone else.