Google Mock : Setting argument in EXPECT_CALL
Asked Answered
S

1

7

I am trying to set a class member function parameter value in Google Mock, but I get build errors and I simply don't understand what is going on. Would it be possible for someone to explain please.

The function prototype is:

virtual int recv( Socket socket
                , char *buffer
                , int bufferLength
                , int flags ) = 0;

I am trying to test it using:

TEST_F( IPV4SocketTests, Read_SockErr_ok )
{
    Mock_SocketAdaptor *adaptor = new Mock_SocketAdaptor;
    char *rcvBuffer = "testingRcvWorks";

    EXPECT_CALL( *adaptor, recv( testing::_, testing::_, testing::_, testing::_ ) )
    .WillRepeatedly( testing::DoAll(
        testing::SetArgPointee<1>( rcvBuffer ),
        testing::Return( strlen( rcvBuffer ) ) ) );

The error I am getting is regarding conversion from std::get.

Suffocate answered 10/2, 2016 at 10:9 Comment(4)
Could you paste in the exact error message? Is it std::get<std::tuple::size_type>() you're having problems with or something else?Centrifugate
Actually, what is testing::SetArgPointee<1>( rcvBuffer ) supposed to achieve? The second/first parametre you passed is just testing::_, so you won't have access to it anyway.Centrifugate
@TomaszKaminski I am still trying to get to grips with this part of Mock, is testing::_ wrong?Suffocate
@TomaszKaminski What do you mean by that "won't be able to access it"? Usage of testing::_ indicates that this parameter won't be matched with some value, there is nothing that prevents SetArgPointee to work like Paul intended.Vitality
V
13

The problem is that rcvBuffer is a pointer. That is why you must dereference it when setting the pointee. Here is how your EXPECT_CALL should look:

EXPECT_CALL( *adaptor, recv( testing::_, testing::_, testing::_, testing::_ ) )
    .WillRepeatedly( testing::DoAll(
        testing::SetArgPointee<1>( *rcvBuffer ),
        testing::Return( strlen( rcvBuffer ) ) ) );

EDIT:

This is the approach I've used in my projects to mock returning a char array through a pointer used as argument. First, you need to create a custom action that will copy the contents of the buffer (you cannot use SetArrayArgument in this case):

ACTION_TEMPLATE(SetArgNPointeeTo, HAS_1_TEMPLATE_PARAMS(unsigned, uIndex), AND_2_VALUE_PARAMS(pData, uiDataSize))
{
    std::memcpy(std::get<uIndex>(args), pData, uiDataSize);
}

Then, in a test use it like this:

Mock_SocketAdaptor *adaptor = new Mock_SocketAdaptor;
char rcvBuffer[] = "testingRcvWorks";
size_t bufferSize = sizeof("testingRcvWorks");

EXPECT_CALL( *adaptor, recv( testing::_, testing::_, testing::_, testing::_ ) )
    .WillRepeatedly( testing::DoAll(
        SetArgNPointeeTo<0>(std::begin(rcvBuffer), bufferSize),
        testing::Return( strlen( rcvBuffer ) ) ) );
Vitality answered 10/2, 2016 at 10:42 Comment(3)
*rcvBuffer returns just the 1st character though, e.g. instead of "testingRcvWorks" I get "t"? It get's rid of the build error though ;)Suffocate
@PaulMorriss Sorry about that, I forgot that using SetArgPointee will only give your the first character. See my updated answer for a detailed decription of how to copy the entire char array.Vitality
@MarkoPopovic Don't apologise, you are helping. That worked an absolute treat, thank youSuffocate

© 2022 - 2024 — McMap. All rights reserved.