我有一段C++代码,它利用Infiniband动词进行RDMA通信。我需要对这段代码进行单元测试,从而测试与RDMA相关的函数调用,如 ibv_get_device_list()
需要在没有任何实际硬件的情况下成功。根据我的理解,我可以做到以下几点。
infinband/verbs.h
在测试过程中。- 原来是非常繁琐的能否使用gmock来模拟这些功能?我还可以考虑哪些其他的方案?
第2条是要走的路。 我要对这个说法提出质疑。
不能这么做,因为这需要对原始代码做太多的修改。
如果一切顺利,你的IDE有一个 "全局搜索和替换 "可以使用。
让我们用最小的破坏性变化来细化抽象出你的代码的最简单方法。
首先定义一个类,简单地封装那些C库函数调用。
class RDMA
{
public:
virtual struct ibv_device **ibv_get_device_list(int *num_devices)
{
return ::ibv_get_device_list(num_devices);
}
virtual void ibv_free_device_list(struct ibv_device **list)
{
return ::ibv_free_device_list(list);
}
virtual uint64_t ibv_get_device_guid(struct ibv_device *device)
{
return ::ibv_get_device_guid(device);
}
};
在上面的类中扩展任何其他你可能需要的相关调用.
在全局范围内,声明一个上述类的实例和一个指向它的指针。
RDMA g_product_code_rdma;
RDMA* g_ptrRMDA = &g_product_code_rdma;
将所有的产品代码调用替换为 ibv
函数,通过全局指针调用到类中。 也就是说,把这个。
ibv_free_device_list(&list);
被调用为。
g_ptrRMDA->ibv_free_device_list(&list);
或者,你也可以声明辅助函数。
ibv_device **global_ibv_get_device_list(int *num_devices)
{
return g_ptrRDMA->ibv_get_device_list(num_devices);
}
然后替换你所有的调用来使用新的 "全局 "版本。 一个简单的 sed/awk 脚本或者直接使用你的 IDE 来全局搜索并替换这些函数调用将是最简单的方法。
在这一点上,你的产品代码的功能和以前一样。
在你的单元测试中,你只需声明一个 MockRDMA
类,继承自 RDMA
类上面。
class MockRDMA : public RDMA
{
public:
ibv_device **ibv_get_device_list(int *num_devices) override
{
// return a fake list of devices
}
virtual void ibv_free_device_list(struct ibv_device **list) override
{
return;
}
virtual uint64_t ibv_get_device_guid(struct ibv_device *device) override
{
return 0x012345678;
}
};
然后你只需在单元测试开始时说这句话。
MockRDMA mock;
g_ptrRDMA = &mock;
Example:
bool test_that_thing()
{
RDMA* original = g_ptrRDMA;
MockRDMA mock;
g_ptrRDMA = &mock;
// test code to validate the code that depends on those RDMA calls
// restore the RDMA class
g_ptrRDMA = original;
return result;
}
如果你决定选择方案3(SoftRoCE),当然也可以让客户端和服务器在同一个主机上。你可以尝试一下 流浪汉箱 我创建的目的是为了在虚拟机中轻松测试SoftRoCE。