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

I am having a hard time storing the pointer argument that my layout gets.

#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 store the first argument of sendData (pointer) and look at the data it points to (it points to a large structure, 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 believe I am storing the value of the pointer in the structure rather than storing the pointer.

I think the problem is with the variable I am passing to SaveArg, but I cannot get it in the version that compiles and gives the correct answer. Any pointers please?

+3


source to share


2 answers


I just ran into the same situation and in my case I had to make sure that the pointer passed to the equivalent of your sendData () function does not point to an automatic variable on the stack. Otherwise, by the time the pointer is accessed, the content will have changed. I found this less useful, so I decided to define a custom SaveArg alternative 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;
}

      



Then you can use it like this:

uint32_t someValue1;
EXPECT_CALL(mock, sendData(_, SIZE_OF_DATA))
    .WillOnce(SaveSomeValue1<0>(&someValue1));
//...
EXPECT_EQ(SOMEVALUEIWANT, someValue1);

      

+6


source


You can create one void pointer as a buffer and store the argument inside that buffer. After that, you have to drop the buffer into your big 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); 

}

      

+1


source







All Articles