1

I am passing a pointer to an array to a function, which I am mocking with googlemock. I would like to verify the contents of the arguments, which works fine for scalars, but I am not able to fetch the elements of the array:

#include <iostream>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
class InterfaceTest : public ::testing::Test {};
class MockFortranFuncInterfacePointerArgs {
public:
  MOCK_METHOD(void, fortran_interface_test_func_pointerargs, (int*, int*));
};

void testfunc_pointer(MockFortranFuncInterfacePointerArgs* func_interface) {
  int testscalar = 123;
  int testarray[3] = {1, 2, 3};
  func_interface->fortran_interface_test_func_pointerargs(&testscalar, &testarray[0]);
}

TEST_F(InterfaceTest, TestFuncInterfacePointerArgs) {
  MockFortranFuncInterfacePointerArgs mock_func_interface;
  int passed_scalar = 0;
  int passed_array[3] = {0, 0, 0};
  // int passed_array = 0;
  EXPECT_CALL(mock_func_interface, fortran_interface_test_func_pointerargs(testing::_, testing::_))
    .WillOnce(testing::DoAll(
        testing::SaveArgPointee<0>(&passed_scalar),
        testing::SetArrayArgument<1>(passed_array, passed_array + 3)
    ));
  testfunc_pointer(&mock_func_interface);
  std::cout << passed_scalar << std::endl; // prints 123
  std::cout << passed_array[0] << " " << passed_array[1] << " " << passed_array[2] << std::endl; // prints 0 0 0
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

How can I modify this test so I am able to verify all three elements of the array that was passed to fortran_interface_test_func_pointerargs? I can't just compare them directly because I need to store the array that was passed in testfunc_pointer first, which is not possible with the current implementation using SetArrayArgument

Yes
  • 339
  • 3
  • 19
  • `SetArrayArgument` is similar to `SetArgPointee` not `SaveArgPointee`... – Jarod42 Mar 31 '23 at 16:47
  • 1
    I voted to reopen since I've try all solutions from duplicate question and from comment above and can't make it work. Here is nice [mcve](https://godbolt.org/z/84WcYxGcv). – Marek R Mar 31 '23 at 18:19
  • 1
    What is funny if there is extra argument providing a size I can [address this issue](https://godbolt.org/z/eh1d1r9fd) ([falling as expected version](https://godbolt.org/z/rGssaea3E)). – Marek R Mar 31 '23 at 18:22
  • 1
    @Yes does first argument describe size of array, but has pointer form? – Marek R Mar 31 '23 at 18:26

1 Answers1

1

Ok I can't find anything in google toolbox which could address this issue.

But this can be solved by providing own matcher:

MATCHER_P2(ArrayPointee, size, subMatcher, "")
{
    return ExplainMatchResult(subMatcher, std::make_tuple(arg, size), result_listener);
}

This matcher allows convert pointer argument to tuple of pointer and size which other matchers are treating like std::span (available since C++20).

So test can be tweaked this way (modification of my MCVE from comment):

#include <gmock/gmock.h>
#include <gtest/gtest.h>

using ::testing::ElementsAre;

MATCHER_P2(ArrayPointee, size, subMatcher, "")
{
    return ExplainMatchResult(subMatcher, std::make_tuple(arg, size), result_listener);
}

class IFoo {
public:
    virtual void foo(int*) = 0;
};

class MockFoo : public IFoo {
public:
    MOCK_METHOD(void, foo, (int*), ());
};

void UseFoo(IFoo& foo)
{
    int arr[] { 3, 5, 7 };
    foo.foo(arr);
}

TEST(TestFoo, fooIsCalledWithProperArray)
{
    MockFoo mock;
    EXPECT_CALL(mock, foo(ArrayPointee(3, ElementsAre(3, 5, 7))));
    UseFoo(mock);
}
Marek R
  • 32,568
  • 6
  • 55
  • 140