Search code examples
c++googlemock

Save C-Style array values using gmock


I have the following expectation on one of my objects:

EXPECT_CALL(usbMock, Write(_, expectedBufferLength));

Where the '_' argument is the buffer being passed to Write function on the usbMock.

I need to get the values inside that buffer, so that I can run my own array comparison function (ElementsAreArray and ElementsAre doesn't work for me, because I needed custom output message with exact contents of expected/actual array, and also my arrays are more than 10 bytes long);

In any case, I got very close to solving my problem with the following:

byte* actualBuffer;
EXPECT_CALL(usbMock, Write(_, expectedBufferLength)).WillOnce(SaveArg<0>(&actualBuffer));

The problem is that this is an integration test, and the buffer pointed to by actualBuffer gets released, by the time I'm able to act on it.

My question is, how can I save the contents of the actualBuffer for later inspection, instead of just getting a pointer to it.


Solution

  • I've found myself in the same situation a couple times, and I have two potential strategies to offer:

    • You can define a custom matcher (see MATCHER_Px macros)
    • You can use Invoke and perform the actions you need in the callback

    In your case, it will depend on whether you know what to expect at the point where the code is invoked: if you already know, then you can define a matcher that takes the expected array in parameter, otherwise if you need to save it you can use the callback in Invoke to perform a deep copy.


    Some code samples:

    // Invoke
    EXPECT_CALL(usbMock, Write(_, expectedBufferLength))
            .WillOnce(Invoke([expectedBuffer](byte* actualBuffer, size_t length) {
                // Substitute for your matching logic
                for (size_t i = 0; i != length; ++i) {
                    EXPECT_EQ(actualBuffer[i], expectedBuffer[i]);
                }
            });
    

    And with the matchers:

    MATCHER_P2(ByteBufferMatcher, buffer, length, "") {
        return std::equal(arg, arg + length, buffer);
    }
    
    // Usage
    EXPECT_CALL(usbMock,
        Write(ByteBufferMatcher(expectedBuffer, expectedLength), expectedLength));
    

    Note that the latter makes it more difficult to supply a custom error message.