软件白盒测试中,需要对待测程序的结构进行分析,根据不同的覆盖策略,设计不同功能的探针函数并确定合适的插入点。同时,为了完成插装、保证搜集到正确的被测程序执行信息,便于统计执行结果以及输出测试报告,还需要进行程序结构的调整、辅助信息的添加等程序修改以及信息的提取操作。
目前常用来进行信息提取修改的工具主要有Gcc、JavaCC等,虽然可以达到目的,但无论实现的复杂度还是可操作性都面临较大的挑战,而Eclipse CDT开源工具提供了有力的支持,基于其强大的方法库以及清晰简洁的架构,我们可以方便地使用程序抽象语法树(AST)信息。本文采用Eclipse CDT开源包,进行待测程序AST的获取,并结合此结构完成覆盖策略实现的部分工作。
1 程序修改与信息提取工具
对源程序进行修改及信息提取主要有以下两种方式:
(1)直接编写针对源程序语言的词法、语法分析器,对源程序进行分析,得到源程序的信息,并在修改后重建。
(2)利用开源工具实现。常用工具属于第一种方式,这种方式特点是,语法识别准确,提取的源代码信息比较准确,编写静态信息输出接口也有利于实现交互,但是由于语言描述比较复杂,实现难度比较大。
2 基于Eclipse CDT的程序修改
2.1 程序标准化
本文所说的标准化,主要是进行源程序结构的调整。主要的调整有:①注释语句的去除②为分支循环语句添加语句块标记“{}”。在AST中注释语句对应的节点类型为IASTComment,当遍历到该类型节点时,不进行其他操作。CASTIfStatement类型对应if语句,CASTCompoundStatement类型对应语句块“{}”节点并作为CASTIfStatement节点的孩子节点出现,因此可以通过判断CASTIfStatement节点下是否存在CASTCompoundStatement节点判断该if语句是否有语句块标记,如果没有的话,在将if语句的对应的token写入新文件之前,应该先写入“{”,然后写入if语句,最后写入“}”,而对应CASTSwitchStatement语句以及循环语句CASTForStatement,CASTWhileStatement等有相似的操作。这样,通过去除注释以及添加花括号,我们得到标准的程序结构,为后续插桩点确定、路径统计等做准备。
2.2 隐藏段的添加
隐藏段的作用主要是用来记录程序的执行路径, 以便于进行覆盖分析、路径分析乃至测试用例生成等工作,列如只有if语句而缺少与之搭配的else语句,就需要在遍历AST的过程中自动添加else隐藏段。
2.3 探针函数的插桩
在对AST访问的过程中,读取之前信息提取时确定的插装点信息,将探针库的头文件“probe.h”以及相应的探针函数调用使用文件流写到文件中。为了不影响源程序的逻辑完整,插入探针函数时可以采用特殊结构,例如逗号表达式、多目表达式等。
3 基于Eclipse CDT的程序信息提取
具体到不同的策略,item可以是可执行语句、条件语句、分支语句和路径等。利用AST节点类型,实现这些信息的统计非常方便。
3.1 统计信息
对于待测程序来说,通过CDT得到的AST中,每一条语句都对应一个IASTStatement节点,统计总的可执行语句数时,只需要排除非可执行语句,然后设置全局变量,对可执行语句进行计数,当AST遍历完成之后,整个待测函数的可执行语句数即可获得。同样,AST中,每个分支、每个条件都会作为单独的节点出现,相应的全局变量即可完成统计。
3.2 计算信息
覆盖测试中的路径总数,需要通过计算获取。分析如下:
对于一条路径,需要考虑两个元素,一是节点,二是节点之间的边。
3.2.1 节点
首先,对于一组顺序执行语句来说,可以将其看作一个节点。对于条件语句来说,情况较为复杂,往往需要考虑条件的类型,具体来说,例如表达式“if(a < b || b < c && c > 1)”,我们需要建立三个节点,节点1为“a < b”,当取真时,则进入if语句块内执行,否则执行节点2“b < c”,对于节点2,当取真时,执行节点3“c > 1”,否则,会直接执行整个if条件表达式为假之后的语句。另外,跳转语句之后不应该与其他节点有边相连。
3.2.2 节点之间的边
根据节点类型,边的关系有,顺序节点与条件节点相连,条件节点与顺序节点相连,条件节点中不同类型的子表达式节点相连,其他节点与跳转节点相连等。
在遍历AST过程中,我们通过节点名来判断节点类型,并以此来建立节点与节点之间的边的关系,可以选邻接矩阵来进行存储表示。当AST访问完成,通过邻接矩阵即可完成路径总数计算。
4 总结
软件白盒测试中,程序信息的修改与获取是关键点,常规工具如Gcc、JavaCC等面临复杂度高,操作不方便的问题,而Eclipse CDT提供了强大的分析功能。在此基础之上,可以集中在覆盖算法设计实现上,本文提出了几种覆盖策略所需条件的算法实现。同时,除了本文中CDT适用于C/C++,基于Eclipse的AST提取工具还可以支持Java、Javascript等,它们都可以同CDT集成,对于完成更加强大通用的应用,提供广泛的支持。