Monday, February 12, 2024

Elegant way to create Segfault with C++ and Google Test

Let's say you have a gRPC interface and several domain classes in your app that rely on that interface. Now you want to implement unit tests for the domain classes. The test suits for each class are split into separate cpp file. In every file, a mock class for the gRPC client class is defined. Mocking only required methods seems a good idea.

ClassFloorTests.cpp

class MockBuildingGrpcClient : public BuildingGrpcClient
{
public:
MockBuildingGrpcClient() : BuildingGrpcClient(nullptr){};
MOCK_METHOD(int, GetFloorList, (), (override));
MOCK_METHOD(int, AddFloor, (string& name), (override));
MOCK_METHOD(int, RemoveFloor, (int id), (override));
};

ClassAppartmentTests.cpp

class MockBuildingGrpcClient : public BuildingGrpcClient
{
public:
MockBuildingGrpcClient() : BuildingGrpcClient(nullptr){};
MOCK_METHOD(int, GetAppartmentList, (), (override));
MOCK_METHOD(int, AddAppartment, (string& name), (override));
MOCK_METHOD(int, RemoveAppartment, (int id), (override));
};

The trap is that for linker these 2 constructors for MockBuildingGrpcClient look the same if they are in the same namespace, which is most probably the case. In both cpp files, the same constructor is called, which is not what the C++ user expects. At some point, this background leads to Segfault. Either at the mock class constructor call or when calling one of the gRPC methods. For me, g++ and the newest cppcheck didn't issue any warnings for this code. Thankfully, after I tried to isolate the problem, it didn't take a lot of time to catch it.

todo: If there is some interest in this topic I might consider adding the output from GDB at the point of Segfault.