如何使用gmock框架模拟c++单元测试中的fork和execlp系统调用
How to mock fork and execlp system calls in c++ unit test using gmock framework?
我有现有的C++代码,它使用fork()系统调用创建一个子进程。子进程使用execl()系统调用执行linux命令。现在,我想使用100%代码覆盖率的gmock框架来测试这段代码。我在谷歌上搜索了很多,但没有得到任何完整的解决方案。有人能帮我吗?
这是我的SUT:
int someclass :: os_fork()
{
pid_t pid = fork();
if (pid == -1) {
cout<<"fork() failed with errno" <<errno <<endl;
return false;
}
if (pid == 0 && (execlp("ls", "ls", nullptr) != 0))
{
cout<<"child process failed with errno"<<errno<<endl;
return false;
}
int ppid = pid;
return 0;
}
我想模拟fork()和execl()系统调用。我怎么能那样做?
不可能模拟全局函数。相反,您可以在一个接口中添加一层抽象并包装系统调用:
class OsInterface {
virtual pid_t fork() = 0;
}
class OsInterfaceImpl : public OsInterface {
virtual pid_t fork() override
{
return ::fork();
}
}
class OsInterfaceMock : public OsInterface {
MOCK_METHOD0(fork, pid_t());
}
这允许您选择真实的系统调用或使用依赖注入的mock。由于你没有提供任何代码,我无法帮你。
通常,您会将指针或对注入类的引用传递给应该使用它的类的构造函数,但很少有其他方法更适合您的项目。
另一个优点是,此代码更为开放-关闭:您可以很容易地(嗯,相对容易地)添加例如Windows实现,而无需更改现有代码-您只需提供另一个继承自OsInterface
的类。您不必更改生产代码中对接口的任何调用,只需更改注入的类即可。
请注意,这不会在单元测试中运行任何额外的进程,但这是一个优势。您应该单独测试进程中运行的代码。
这有点晚了,但您可以重新定义它,并"注入"MockFunction以产生一些期望。我想是某种勾搭。
#define CALL_ORIGINAL -2
testing::MockFunction<int()> forkHelp;
pid_t fork(void)
{
auto mockResult = forkHelp.Call();
if (CALL_ORIGINAL != mockResult)
{
return mockResult;
}
return syscall(SYS_fork); /* Hack for calling real syscall */
}
附言:这种方法会失败的。在测试结束时,它会说你的代码leaaks),所以这取决于你来解决这个问题。
相关文章:
- execlp() 在 fork() 之后无法正常工作
- 在 fork() 之后,我在我的程序中不断得到相同的 pid
- 从stdin读取时子进程挂起(fork/dup2竞争条件)
- 为什么if(fork()==0){getpid()}和popen()进程返回相同的进程id
- While循环在fork和execvp调用后没有继续
- fork(),在C中共享内存和指针
- fork/pipes和运行多个程序
- Gdb 未加载要在 fork 使用的源文件
- fork() 无法使用 Cygwin
- PID 不使用 fork() 定义类型
- 为什么我应该使用 fork() 来守护我的进程?
- 修改跨 fork() 的指针中的数据
- C++ fork() 和 execl() 调用 (Linux) 后无法识别命令
- 来自 execlp 的多行输出
- 在 fork() 之后,如何在 for() 循环中继续运行 execve()
- 如何在最后一个子 fork() 下打印带有其名称和 pid 的子进程
- fork()和exec()两个子进程
- 我试图了解 fork() 函数序列是如何工作的?
- 如何使用gmock框架模拟c++单元测试中的fork和execlp系统调用
- 在Linux中使用fork()+execlp和boost::asio时出现地址重用错误