嵌入式软件的覆盖测试
*与其它嵌入式交叉开发工具的关系
嵌入式应用程序的开发通常采用交叉开发方式,几乎所有的开发工具均要解决3部分的问题:宿主机部分的功能、目标机部分的功能、宿主机与目标机的连接问题。其中,宿主机与目标机的连接是个瓶颈,如果不同的工具要使用同一物理线路实现数据传输,则要解决对该物理线路(或者说硬件端口)的正确共享。比如在图3所示的环境中,宿主机方的各种工具通过统一的接口——目标服务器(target server)实现对通信线路的访问,目标机方的调试代理(debug agent)则是各种信息(调试信息、覆盖信息、时间信息、对象信息等)的收集与传递的核心。
5 Logiscope在嵌入式操作系统DeltaCORE测试中的应用
Logiscope是Verilog公司的CASE产品,对软件的编码、测试、维护提供多方面的服务,并且支持嵌入式软件的覆盖测试。
5.1 测试前的准备
测试前的准备即为支持对DeltaCORE的测试所做的移植工作。
目前,Logiscope已经为一些成熟的商用嵌入式操作系统提供了支持,比如pSOS。DeltaCORE是我国自主开发的嵌入式强实时操作系统内核,为了利用Logiscope实现对DeltaCORE的应用程序乃至DeltaCORE本身的测试,我们主要解决了第4节中描述的第1个关键问题。
javascript:window.open(this.src);" style="cursor:pointer;"/>
*1个用来收集和发送覆盖信息的主循环线程,该线程即是嵌入式应用中的特殊任务;
*实现具体数据传输的函数,包括对串口或网络的驱动,它们将被上述线程调用;
*插装函数的实现,这些函数被被测代码调用,向缓冲中放入覆盖消息块;
*对缓冲信息队列的管理;
*初始化代码。
例如,当被测程序运行进入到一条if(……)语句时,整个过程如图4所示。
为了支持对DeltaCORE的测试,将与这些机制相关的代码进行移植,包括以下几方面:
*将收集和发送覆盖信息的主循环线程作为在目标机端运行的应用程序中的特殊任务;
*对串口的驱动采用LambdaTOOL BSP(板级支持包)中的串口驱动代替,对网络的驱动,用DeltaCORE的配套组件DeltaNET中的驱动程序实现;
*利用DeltaCORE的信箱机制实现消息队列的创建和管理,插装代码向这些信箱发送覆盖消息块;
*在DetaCORE应用程序的根任务中调用Logiscope的初始化函数,达到创建特殊任务信箱的目的。
开发DeltaCORE应用程序时,我们使用了其配套开发工具LambdaTOOL。由于所使用的工具版本没有实现目标服务器(target server)的调试方式,因此对物理端口的使用采用的独占方式,即调试工具不能与其它工具共享同一端口。我们可以用网络试上载并启动目标应用程序,而通过串口传送覆盖信息。
5.2 对DeltaCORE的覆盖测试过程及结果
对于函数内部,Logiscope支持的覆盖策略有:
*指令块IBs(Instruction Blocks)
*判断到判断的路径DDPs(Decision-to-Decision Paths)
*MCDC(Modified Condition/Decision)
在项目层次上支持的覆盖策略是:
*过程到过程路径PPP(Procedure-to-Procedure Path)
在DeltaCORE的测试中,我们采用了较为常用的覆盖策略——判断到判断的路径,其含义是:DDP是一个指令序列,它的起点是函数或判断(if,while,……)的入口点,它的出口是下一个函数或判断的退出点,之间不能再有判断,比如在图5中包含了5个DDPs:
测试的具体过程是:
①利用插装分析器对DeltaCORE的源代码进行插装,并生成插装信息文件。
②将移植后的Logiscope目标机端程序与插装后的内核源代码一同编译链接成库,以替代原来的内核库,供应用程序使用。
③编写测试案例,从实现应用的角度使用DeltaCORE的各种系统功能调用,力求遍历内核函数所有的判定分支,并将这些案例编译成可执行程序。javascript:window.open(this.src);" style="cursor:pointer;"/>
④在宿主机端启动覆盖信息收集和分析程序,用LambdaTOOL的调试器下载并启动应用程序。DeltaCORE的覆盖信息被传递到宿主机上,分析程序动态显示覆盖率的增长情况,并将这些信息记录在一个文件中。
⑤应用程序执行完毕后,启动Logiscope的事后分析工具,将覆盖信息记录文件与插装信息文件(在源代码插装在生成的附属文件)进行比较,帮助测试人员清晰地了解每个被测函数内部的路径覆盖情况,借此可为测试案例的改进提供帮助。
⑥测试人员修改测试案例,并重新进行整个测试过程;各项测试的结果可以叠加,覆盖率将得到增长。
经过2个多月的时间,我们对DeltaCORE 1.1版本79个文件共计115个函数进行了覆盖测试,覆盖率已经达到了70.55%。编写测试用例89个,主要的60个API函数均已获得较高的覆盖,覆盖率达100%的约占51.3%。
6 小结
我们借助Logiscope工具对嵌入式实时操作系统DeltaCORE进行了覆盖测试,达到了较好的覆盖率;发现并处理了一些缺陷,提高了软件的质量和可靠性,但同时也存在不足之处:
①测试应好好规划,包括测试顺序的选择、测试案例的设计、测试文档的管理等等。
②由于该测试手段依赖于操作系统的有关机制,而被测对象又是操作系统本身,因此与这些机制有关的部分代码未被插装和测试,否则就会出错。比如,操作系统的初始化函数os_init,在这个函数运行完毕之前,操作系统的相应机制尚未建立起来,因此对它进行插装就会造成问题,不能正确地得到覆盖信息。又比如,出于效率方面的考虑,与系统时钟相关的部分函数未被插装,因为在程序运行过程中,时钟是最频繁产生的一种外部事件,如果插装,就会产生大量的覆盖信息,会对信息缓存、传递、收集和处理造成压力。另外,所用的工具不支持对汇编函数的插装和测试。综合上述各种原因,DeltaCORE 1.1的总体覆盖率还显得比较低,需要采用其它的方法来提高它。对于非操作系统组件及应用的测试,由于不存在操作系统本身的问题,因此可望达到较高的覆盖率。
③该方法不能用于时间性能测试。因此它属于纯软件的测试方式,大量数据信息的产生、传递与收集对被测程序的干扰大,只能做白盒性的功能结构验证。如果做性能测试,应采用某些软硬结合方式的工具,比如CodeTEST。
对嵌入式软件产品的测试是多方面的,除覆盖测试外,还有时间性能测试、内存使用测试与分析等,也是我们研究的重要课题。