C 单元测试:存根常量结构 (gcc --wrap)
C Unit Test: stub a constant structure (gcc --wrap)
大家好这是我的具体案例:
service.h:
typedef struct {
uint8_t (*function1)(void);
uint8_t (*function2)(void);
} const service_struct_t;
extern service_struct_t service_api ;
service.c:
#include "service.h"
static uint8_t foo(void){
return 13+6;
}
static uint8_t bar(void){
return 7*6;
}
service_struct_t service_api = {
.function1 = foo,
.function2 = bar,
};
我需要存根(模拟、替换)这些函数,但我无权更改原始代码。我正在使用 gcc 来编译单元测试。我没能:
- 直接在
foo
和 bar
上使用 gcc 的 --wrap 选项,因为它们对于 source.c 是静态的:
#include "service.h"
#define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
uint8_t __real_foo(void);
uint8_t __wrap_foo(void){
if(ENABLE_STUB){
return 1;
}else{
return __real_foo();
}
}
/* same for bar */
- 在
service_api
对象符号上使用 gcc 的 --wrap 选项,因为它不是函数
#include "service.h"
#define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
uint8_t __real_service_api ;
uint8_t __wrap_service_api = {
.function1 = foo,
.function2 = bar,
}
static uint8_t foo(void){
if(ENABLE_STUB){
return 1;
}else{
return __real_service_api.function1();
}
}
/* same for bar */
- 只需重新分配
service_api
成员函数,因为结构是常量并且已经分配。
#include "service.h"
#define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
service_struct_t backup_service_api = {
.function1 = service_api.function1;
.function2 = service_api.function2;
}
service_struct_t stub_service_api = {
.function1 = foo;
.function2 = bar;
}
uint8_t foo(void){
if(ENABLE_STUB){
return 1;
}else{
return __real_foo();
}
}/* same for bar */
void service_poke_stub(bool_t enable_stubs){
if(enable_stubs){
service_api.function1 = stub_service_api.function1
service_api.function2 = stub_service_api.function2
}else{
service_api.function1 = backup_service_api.function1
service_api.function2 = backup_service_api.function2
}
}
非常感谢你的帮助
正如您已经发现的那样,您不能模拟结构中的函数。
所以这取决于你想测试什么:
如果您想测试结构是否包含正确的功能,模块 service.c
是您的待测模块,应按原样使用。您需要通过观察函数执行的操作来检查正确性。
如果你想测试结构是否被正确使用,你将模拟整个模块。现在你想放什么就放什么。
如果您的源代码不允许这样做,则该设计不利于测试。当架构没有考虑到可测试性时,通常会出现这种情况。
大家好这是我的具体案例:
service.h:
typedef struct {
uint8_t (*function1)(void);
uint8_t (*function2)(void);
} const service_struct_t;
extern service_struct_t service_api ;
service.c:
#include "service.h"
static uint8_t foo(void){
return 13+6;
}
static uint8_t bar(void){
return 7*6;
}
service_struct_t service_api = {
.function1 = foo,
.function2 = bar,
};
我需要存根(模拟、替换)这些函数,但我无权更改原始代码。我正在使用 gcc 来编译单元测试。我没能:
- 直接在
foo
和bar
上使用 gcc 的 --wrap 选项,因为它们对于 source.c 是静态的:
#include "service.h"
#define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
uint8_t __real_foo(void);
uint8_t __wrap_foo(void){
if(ENABLE_STUB){
return 1;
}else{
return __real_foo();
}
}
/* same for bar */
- 在
service_api
对象符号上使用 gcc 的 --wrap 选项,因为它不是函数
#include "service.h"
#define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
uint8_t __real_service_api ;
uint8_t __wrap_service_api = {
.function1 = foo,
.function2 = bar,
}
static uint8_t foo(void){
if(ENABLE_STUB){
return 1;
}else{
return __real_service_api.function1();
}
}
/* same for bar */
- 只需重新分配
service_api
成员函数,因为结构是常量并且已经分配。
#include "service.h"
#define ENABLE_STUB 1 /* that is actually a variable toggled at runtime */
service_struct_t backup_service_api = {
.function1 = service_api.function1;
.function2 = service_api.function2;
}
service_struct_t stub_service_api = {
.function1 = foo;
.function2 = bar;
}
uint8_t foo(void){
if(ENABLE_STUB){
return 1;
}else{
return __real_foo();
}
}/* same for bar */
void service_poke_stub(bool_t enable_stubs){
if(enable_stubs){
service_api.function1 = stub_service_api.function1
service_api.function2 = stub_service_api.function2
}else{
service_api.function1 = backup_service_api.function1
service_api.function2 = backup_service_api.function2
}
}
非常感谢你的帮助
正如您已经发现的那样,您不能模拟结构中的函数。
所以这取决于你想测试什么:
如果您想测试结构是否包含正确的功能,模块
service.c
是您的待测模块,应按原样使用。您需要通过观察函数执行的操作来检查正确性。如果你想测试结构是否被正确使用,你将模拟整个模块。现在你想放什么就放什么。
如果您的源代码不允许这样做,则该设计不利于测试。当架构没有考虑到可测试性时,通常会出现这种情况。