在gtest.中使用fff.h模拟系统API
Mocking of System API using fff.h in gtest
我在gtest中使用fff.h模拟calloc函数时遇到问题。有谁能指导我如何解决这个问题吗我的代码在下面。
#include <iostream>
#include "gtest/gtest.h"
#include "stub_sys.h"
#include "sav_v2x_secif.h"
#include "fff.h"
extern "C" {
DEFINE_FFF_GLOBALS;
//FAKE_VALUE_FUNC(void *, calloc, size_t, size_t);
FAKE_VALUE_FUNC(void *, malloc, size_t);
}
我得到以下错误输出。
X86/staging_dir/include/fff.h:1679:68: error: declaration of ‘void* malloc(size_t)’ has a different exception specifier
RETURN_TYPE FFF_GCC_FUNCTION_ATTRIBUTES FUNCNAME(ARG0_TYPE arg0){
^
X86/staging_dir/include/fff.h:6524:19: note: in definition of macro ‘EXPAND’
#define EXPAND(x) x
^
X86/staging_dir/include/fff.h:6548:32: note: in expansion of macro ‘EXPAND’
#define FUNC_VALUE_(N,...) EXPAND(FUNC_VALUE_N(N,__VA_ARGS__))
^
X86/staging_dir/include/fff.h:6550:33: note: in expansion of macro ‘EXPAND’
#define FUNC_VALUE_N(N,...) EXPAND(FAKE_VALUE_FUNC ## N(__VA_ARGS__))
^
X86/staging_dir/include/fff.h:1714:5: note: in expansion of macro ‘DEFINE_FAKE_VALUE_FUNC1’
DEFINE_FAKE_VALUE_FUNC1(RETURN_TYPE, FUNCNAME, ARG0_TYPE)
^
X86/staging_dir/include/fff.h:6550:40: note: in expansion of macro ‘FAKE_VALUE_FUNC1’
#define FUNC_VALUE_N(N,...) EXPAND(FAKE_VALUE_FUNC ## N(__VA_ARGS__))
^
X86/staging_dir/include/fff.h:6548:39: note: in expansion of macro ‘FUNC_VALUE_N’
#define FUNC_VALUE_(N,...) EXPAND(FUNC_VALUE_N(N,__VA_ARGS__))
^
X86/staging_dir/include/fff.h:6546:41: note: in expansion of macro ‘FUNC_VALUE_’
#define FAKE_VALUE_FUNC(...) EXPAND(FUNC_VALUE_(PP_NARG_MINUS2(__VA_ARGS__), __VA_ARGS__))
^
X86/tmp/tmp/test/test_tmp.cpp:10:5: note: in expansion of macro ‘FAKE_VALUE_FUNC’
FAKE_VALUE_FUNC(void *, malloc, size_t);
^
X86/tmp/tmp/test/test_tmp.cpp:10:29: error: from previous declaration ‘void* malloc(size_t) throw ()’
FAKE_VALUE_FUNC(void *, malloc, size_t);
我最近写了一个测试来检查memcpy
是否在某些条件下被调用,所以我将添加我的2c:
-
我不认为你真的可以模拟系统调用,因为你可能会破坏底层的C/C++机制。如果您模拟
malloc
,C++标准库将如何分配内存? -
由于上面的#1,你必须跳过额外的关卡,才能检查是否有人调用了什么东西,等等,而不破坏其他东西。
为了测试系统调用,我使用了链接器包装。
-换行=符号对符号使用包装函数。对符号的任何未定义的引用将被解析为"0"_包装符号";。任何未定义的对"_real符号";将解析为符号。
这是一篇很好的文章。
我非常喜欢FFF,但在这种特殊情况下,我不能使用FFF.custom_fake=__real_memcpy
,因为我马上就得到了segfault
。
我对调用memcpy
的次数进行计数的测试是:
// Bit of hackery to intercep calls to memcpy.
//
// We use the linker to wrap memcpy (memcpy is now __real_memcpy) and then
// provide the __wrap_memcpy function so we can count how many times it was
// called.
//
// I've tried using FFF to mock __wrap_memcpy and then do
//
// `__wrap_memcpy_fake.custom_fake = __real_memcpy;`
//
// But I get a sigfault right away, so I had to repliacte a bit of FFF's
// functionality. OTOH I didn't have to add fff.h
extern "C"
{
void* __wrap_memcpy(void* dst, const void* src, size_t n);
extern void *__real_memcpy(void* dst, const void* src, size_t n);
}
size_t __wrap_memcpy_call_count;
void* __wrap_memcpy(void* dst, const void* src, size_t n)
{
__wrap_memcpy_call_count++;
return __real_memcpy(dst, src, n);
}
class TestMemcpyFixture:public ::testing::Test {
public:
void SetUp() override
{
__wrap_memcpy_call_count = 0;
}
};
TEST_F(TestMemcpyFixture, test_memcpy) {
// Do stuff that potentially uses memcpy
void *src, *dst;
// Reset the counter
__wrap_memcpy_call_count = 0;
ASSERT_EQ(0, my_code_that_calls_memcpy(src, dst, 42));
// memcpy must have been called only once
ASSERT_EQ(1, __wrap_memcpy_call_count);
}
链接测试时,请使用链接器选项-Wl,--wrap=memcpy
。正常运行测试。
好的,那么现在malloc
呢?我会在图片类中添加一个标志,用于控制malloc
是否成功。
干杯!
相关文章:
- 有什么好的方法可以让系统调用代理允许在单元测试中进行模拟
- 在gtest.中使用fff.h模拟系统API
- 如何在 Windows API 中更改系统范围的多个游标
- 设置我的应用程序 API 感知并防止系统使其模糊和错误定位
- C++ 窗口本地系统模拟在子进程中失败
- Windows 文件系统 API 不同的输出
- 如何监视应用程序进行的Windows系统API调用?
- 如何在应用程序正在运行的系统上查看所需的Windows API函数
- 如何使用 Linux API for C 确定文件系统类型(名称)?
- 如何测试仅返回系统值的API
- 如何使用gmock框架模拟c++单元测试中的fork和execlp系统调用
- 如何通过Chrome Pepper C API创建和打开文件系统
- 事件记录API未写入系统日志
- C++shell api-系统托盘气泡上的垃圾字符
- MySQL Windows c api 命名管道错误:"在'等待初始通信数据包'时丢失与 MySQL 服务器的连接,系统错误:0
- 模拟系统调用——有更好的方法吗
- 常见日志文件系统 API 的 RegisterManageableLogClient() 和"access is denied"错误
- 尝试挂接到 MessageBeep 系统 API
- 用于查询大文件的 Windows 文件系统 API
- 是否有可能在C中使用系统api启动一个kill命令?如果没有其他选择的话