为什么 void * 指向 gmock 中的 SetArgPointee 的指针会导致错误

Why does void * pointer to SetArgPointee in gmock cause error

考虑一下:

struct INFO {
  unsigned char a;
  int b;
  char c[100];
};
...
INFO inf = {'X', 1010, "AOK Message"};
void *mdptr_s = reinterpret_cast<void *>(&inf);
size_t msiz1 = sizeof(inf);

模拟是:

MOCK_METHOD((size_t), recv, (void *buf_, size_t len_), (override));

在我的模拟测试中有一个 EXPECT_CALL 使用:

.WillRepeatedly(DoAll(
SetArgPointee<0>(mdptr_s), Return(msiz1)));

为什么这会导致错误?

/usr/local/include/gmock/gmock-actions.h:780:5: error: ‘void*’ is not a pointer-to-object type
     *::std::get(std::tie(args...)) = value;
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

相关gmock代码为:

// Implements the SetArgumentPointee<N>(x) action for any function
// whose N-th argument (0-based) is a pointer to x's type.
template <size_t N, typename A, typename = void>
struct SetArgumentPointeeAction {
  A value;

  template <typename... Args>
  void operator()(const Args&... args) const {
    *::std::get<N>(std::tie(args...)) = value;
  }
};

完整代码

mock_turtle_test.cc

#include "mock_turtle.h"
#include "painter.h"
#include <gtest/gtest.h>

using  ::testing::_;
using  ::testing::AtLeast;
using  ::testing::Return;
using  ::testing::DoAll;
using  ::testing::SetArgPointee;

struct INFO {
  unsigned char a;
  int b;
  char c[100];
};

TEST(PainterTest, CanDrawSomething) {
    INFO inf = {'X', 1010, "AOK Message"};
    INFO spl_dat;
    size_t msiz1 = sizeof(inf);
    void *mdptr_s = reinterpret_cast<void *>(&inf);
    Painter painter;
    EXPECT_CALL(*painter.turtle, setSpecial(_,_))
        .Times(AtLeast(1))
        .WillRepeatedly(DoAll(
            SetArgPointee<0>(mdptr_s), Return(msiz1)));
    EXPECT_TRUE(painter.callSpecial(&spl_dat));
}

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

mock_turtle.h

#pragma once
#include <cstdlib>
#include <gmock/gmock.h>

class FakeTurtle {

public:
  virtual ~FakeTurtle() {}
  virtual int setSpecial(void* buf, size_t len);
};

class Turtle : public FakeTurtle{
 public:
  using FakeTurtle::FakeTurtle;
  MOCK_METHOD((int), setSpecial, (void *buf, size_t len),(override));
};

painter.h

#pragma once

class Painter
{
public:
    Turtle* turtle;
    Painter() : turtle(new Turtle){}
    Turtle** getTurtle(){
        return &turtle;
    }
    template <typename T>
    int callSpecial(T *buf){
        void *dptr = reinterpret_cast<void *>(buf);
        size_t sz = sizeof(T);
        return turtle->setSpecial(dptr, sz);
    }
    ~Painter(){
        if(turtle != NULL)
            delete turtle;
    }
};

CMakeLists.txt

cmake_minimum_required(VERSION 2.6)

# Locate GTest
find_package(GTest REQUIRED)
find_package(PkgConfig)
message(STATUS "gtest found: " ${GTEST_FOUND})
pkg_check_modules(GMOCK "gmock" REQUIRED)
message(STATUS "gmock found: " ${GMOCK_FOUND})

include_directories(${GTEST_INCLUDE_DIRS})

# Link runTests with what we want to test and the GTest and pthread library
add_executable(runTests mock_turtle_test.cc)
target_link_libraries(runTests ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} gmock gmock_main gtest gtest_main)
add_test(NAME runTests COMMAND runTests)
enable_testing()

在另一个线程上提出并回答了类似的问题,也许这会有所帮助:https://groups.google.com/forum/#!topic/googlemock/sWBP2q8VZaA