如何在C中模拟Linux系统调用

时间:2017-07-09 21:51:49

标签: c linux unit-testing mocking

在编写使用linux系统调用的C模块时,为了测试模块,模拟这些调用的最佳做法是什么?是否有任何库可以为linux系统调用提供模拟?

"我的-module.h中" - 界面描述

#include "unistd.h"
int mm_foo(int);
int mm_bar(int);

"我的-的module.c" - 要测试的模块。

#include "my-module.h"
int mm_foo(int arg) {

    ...
    int write_ret = write(...);
    ...

};
int mm_bar(int arg) {

    ...
    int read_ret = read(...);
    ...
};

"我的-module.test.cpp" - 单元测试我希望这种方式工作的方式(例如我使用谷歌单元测试)。

#include "my-module.h"

TEST(MyModule, FooTest) {

    reset(write_mock);

    ...

    // this is pure imagination
    write_mock.return_value = -1; // failure
    write_mock.expected_args.fd = somefd;

    int ret_val = mm_foo(somearg);

    ASSERT_EQ(exp_val, ret_val);
    verify(write_mock);

}

当我想模拟一些没有系统调用的东西时,我可以从头文件创建一个替代的接口实现,并将一个模拟实现编译到测试中。但是如何使用系统调用执行此操作。我可以重新实现(覆盖)函数调用吗?我的模块应该调用函数调用的包装器模块吗?

1 个答案:

答案 0 :(得分:1)

通常,您希望为正在测试的每个系统调用创建一个包装器。 A good way to do this and make your code easy to follow, would be just to use the ld option: --wrap。这使您可以在构建时交换符号,而无需重新编写代码来使用包装函数代替真正的libc函数。

Additionally, you could use LD_PRELOAD to override libc system call wrapper functions,就像rootkit /病毒编写者一样,但涉及的工作多于使用--wrap功能。

最后,您可以在包装函数中utilize a unit test framework (i.e. CUnit),简化测试。