如何存根声明为“extern void _x”

时间:2016-03-06 16:04:43

标签: c unit-testing gcc

我需要对c文件/模块进行单元测试,文件包含:

/* Import the _x symbol from assem.S */
extern void _x;

该变量稍后在该文件中用作:

#define WHAT_EVER (int)&_x

汇编程序文件中的减速度为:

.global _x
.type _x, @function
_x:

我学会了here GCC对此声明没问题。 但是我学会here我不能简单地声明:

void _x;

作为我的存根,因为这使得_x成为一个不完整的类型。实际上链接器会抱怨错误:'_x'的存储大小未知且链接器是正确的。

但如果我宣布:

int _x;

编译器给了我错误:'_x'的冲突类型,这也是正确的。

该软件的目标与我进行单元测试的主机不同,因此我不能包含assem.S文件(它不会在我的主机上编译和/或运行)。

有没有人知道如何存根这个变量_x?

GCC 5.3.1; std = gnu99; c代码

1 个答案:

答案 0 :(得分:0)

如果您可以选择修改引用_x的文件,则应将对此符号的访问权限提取为自己的文件。首先,我将解释你如何做到这一点,其次,为什么你应该这样做。

如何提取它?在现有的测试文件中,您可以通过调用访问函数来替换对符号的所有访问。也就是说,您可以调用WHAT_EVER,而不是使用宏get_what_ever()的值进行阅读。如果您使用该符号修改地址,请致电set_what_ever(value)。这些getter和setter函数在一个单独的文件中实现(让我们调用它,例如,interface_to_assembly.c)。声明放在头文件interface_to_assembly.h中。现在,对于目标系统,编译并链接修改后的文件interface_to_assembly.c。对于测试可执行文件,您可以为interface_to_assembly.c创建替代实现,可能是interface_to_assembly_double.c。这些替代实现可能是dummys,stubs,spys,mocks或您测试所需的任何内容。

为什么这种分离值得推荐?首先,它消除了要从程序集级别测试的代码与可能的硬件之间的紧密耦合。其次,它用更好的可控函数接口替换对全局变量的访问。但请注意,文件interface_to_assembly.c中的小软件仍然无法比以前更好地测试(也就是说,它将成为目标系统上集成测试的候选者)。但是,对于剩余的代码(可能是大多数代码),您可以提高可测性:提取变量访问权限并用函数替换它可以编译代码而无需任何汇编级代码。它允许控制每个单一的值访问。例如,可以创建一个测试设置,以便对getter的连续调用提供不同的值(如果您想模拟硬件设备的并发活动,这很重要。)