Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Google Mock SaveArg : how to save a pointer argument

Tags:

c++

googlemock

I having difficulty saving a pointer argument that my mock receives.

#define SIZE_OF_DATA

typedef struct {
    uint32_t someValue1;
    uint16_t someValue2;
    // other values here
} LargeStruct;


class SomeClass {
public:
    // assume sendData is a generic function where data is actually pointer to a LargeStruct
    void sendData(const uint8_t* data, const uint16_t size);
}

class MockClass : public SomeClass {
public:
    MOCK_METHOD2(sendData, void(const uint8_t*, const uint16_t));
};

I want to save the first argument to sendData (the pointer) and look at the data it points to (it points to a large struct, so I don't want to copy by value):

TEST(SomeFixture, sendData_checkSentDataIsValid) {
   MockClass mock;

  const uint8_t *pData;
  EXPECT_CALL(mock, sendData(_, SIZE_OF_DATA)).WillOnce(SaveArg<0>(&pData));

  // do something here that calls sendData()

  // hopefully data should point to the same data that was passed in to the method
  LargeStruct *ls = (LargeStruct *)pData;

  // now verify that the data is ok...
  // some expectations here
  EXPECT_EQ(SOMEVALUEIWANT, ls->someValue1); 

}

However, the data pointed to by pData is wrong - I think I appear to be saving the pointer value into the struct, rather than saving the pointer.

I think the problem lies in the variable I pass to SaveArg, but I can't seem to get it in a version that compiles and gives me the correct answer. Any pointers please?

like image 699
John Avatar asked Sep 17 '14 12:09

John


People also ask

What is difference between On_call and Expect_call?

So use ON_CALL by default, and only use EXPECT_CALL when you actually intend to verify that the call is made.

How do you mock in Gmock?

Using the Turtle interface as example, here are the simple steps you need to follow: Derive a class MockTurtle from Turtle . Take a virtual function of Turtle (while it's possible to mock non-virtual methods using templates, it's much more involved). In the public: section of the child class, write MOCK_METHOD();

How do you mock a function in Gtest?

There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.

What is expect call in Gmock?

In gMock we use the EXPECT_CALL() macro to set an expectation on a mock method. The general syntax is: EXPECT_CALL(mock_object, method(matchers)) . Times(cardinality) .


2 Answers

I just ran into the same situation, and in my case, I had to make sure that the pointer passed into the equivalent of your sendData() function was not pointing to an automatic variable on the stack. Otherwise, by the time you access the pointer, the contents will have changed. I found that less than helpful, so I decided to define a customized alternative to SaveArg like this:

ACTION_TEMPLATE(SaveSomeValue1,
                HAS_1_TEMPLATE_PARAMS(int, k),
                AND_1_VALUE_PARAMS(pointer))
{
    const void * data = ::std::tr1::get<k>(args);
    const LargeStruct* ls = (const LargeStruct *)data;
    *pointer = ls->someValue1;
}

You can then use it like this:

uint32_t someValue1;
EXPECT_CALL(mock, sendData(_, SIZE_OF_DATA))
    .WillOnce(SaveSomeValue1<0>(&someValue1));
//...
EXPECT_EQ(SOMEVALUEIWANT, someValue1);
like image 157
Dale Stewart Avatar answered Oct 13 '22 06:10

Dale Stewart


You can create one void pointer as a buffer and save argument inside that buffer. After that you should cast the buffer to your large structure.

 TEST(SomeFixture, sendData_checkSentDataIsValid) {
  MockClass mock;
  LargeStruct *ls;
  void *buffer;

  EXPECT_CALL(mock, sendData(_, SIZE_OF_DATA))
             .WillOnce(SaveArg<0>(&buffer));

 // do something here that calls sendData()

  ls = static_cast<LargeStruct  *>(buffer);

  EXPECT_EQ(SOMEVALUEIWANT, ls->someValue1); 

}
like image 36
Igor Mišić Avatar answered Oct 13 '22 04:10

Igor Mišić