对于Testbed调用关系的查看,并不是只把一张图打开就可以了,更重要的是通过这种调用关系,来把各个函数之间的入口、出口以及依赖边界给看清楚。一般情况下,调用关系图是结合着静态分析的结果一起生成的,大家经常用它来理解模块的结构、对函数的依赖进行检查、还有把没测试到的调用路径找出来,另外对覆盖率分析和代码评审也能起到一些辅助作用。
一、Testbed调用关系的查看方式
在LDRA工具链里面,静态和动态分析的基础是由Testbed提供的,TBvision比较侧重于数据流、控制流以及把结果给可视化出来,而在单元测试和覆盖率的场景中,TBrun也可以把调用图、流程图和逐行视图展示给大家看。
1、需要先把工程解析给做完
在Testbed项目被打开了之后,大家要先确认一下源文件、头文件、宏定义还有编译器选项是不是都配好了。如果代码里面还存在着大量的解析错误,那么调用图大概率就会把边和节点给漏掉。特别是在嵌入式工程里面,很多函数的声明都是从芯片SDK、平台层、RTOS接口或者公司的公共库里面来的,要是没有把这些路径配进去,工具就很难把完整的关系建立起来。
2、进到调用关系或者控制流的视图里面
当分析被完成了以后,大家就可以在结果视图里面去把函数级的调用关系给看一看。一般可以从文件、函数或者过程的入口点进去,然后再去看当前这个函数到底调用了哪些下级函数,或者是反过来看看有哪些上级函数调用了它。
在LDRA关于数据流和控制流分析的那些说明里面有写到,控制流分析会用图形的方式把程序可能存在的执行顺序呈现出来,这样就能帮开发人员去把代码的行为理解一下。
3、围着关键的函数去把上下游展开
在看调用图的时候,不建议大家一上来就把整个项目都展开。因为项目的函数要是太多了,图就会变得特别乱。大家可以先把核心的入口函数选出来,像是初始化入口、任务调度函数、通信处理函数还有诊断处理函数这些,然后再去向下展开个一级或者两级调用。对于排查问题这件事来说,局部的调用链往往比那种全量的大图要更有用一些。
二、Testbed调用关系图不完整时的排查步骤
如果调用关系图不完整,常见的表现就是函数节点没了、调用线断开了、外部函数显示得很奇怪,或者是有些模块根本没被放进图里。在排查的时候,大家不要直接就觉得是工具有问题,应该从工程的范围、编译的上下文还有代码的写法这三个方面去一步步地确认。
1、检查源文件是不是全都放进分析范围里了
如果有些.c或者.cpp文件没有被导入进来,那图上自然就看不到里面的函数了。特别是在分层架构的工程里面,虽然把应用层的文件导入了,但是平台适配层、驱动层还有通信栈的文件要是漏掉了,就会导致有很多外部调用出现。在处理的时候,大家得去检查一下【Project Files】或者对应的工作文件列表,确认被测模块和它依赖的模块是不是都在这个分析范围里面。
2、对头文件的路径和函数的声明进行核对
调用关系的建立,是要靠函数的声明和定义能匹配上的。如果头文件的路径留得不完整,工具可能就只能看到调用的语句,但是找不到被调函数的定义在哪。常见的现象就是函数名变成了一个外部符号,或者调用线点进去没办法继续展开了。这个时候大家就得把【Include Path】给补齐,尤其是公共头文件、平台头文件、SDK头文件还有那些自动生成代码的目录。
3、确认宏定义和条件编译的分支情况
很多的嵌入式项目,都会用宏来控制不同的平台、不同的配置以及不同的功能开关。在真实编译的时候,项目走的是A分支,但要是没在Testbed里面把对应的宏配好,工具可能就会跑到B分支去分析了,这样调用关系就会和实际的项目对不上。如果遇到了这种情况,大家就要对照着编译脚本、IDE工程的配置或者构建的日志,把关键的【Define/Macro】给补进去。
三、调用关系图在代码审查和测试补充中的使用办法
当把调用关系图看完了之后,大家不能只把截图保存下来就完事了。更有价值的做法,是把它用到模块边界的检查、影响范围的分析、测试的补充以及缺口的解释上面。特别是在对老代码进行修改的时候,先把调用链看一看,能帮大家减少很多不小心改错的风险。
1、用调用链来对修改的影响范围进行判断
在对一个底层函数进行修改之前,大家可以先去看看有哪些上层函数会调用它。如果调用方都集中在某一个模块里面,那影响面就是比较好控制的;但要是它被好几个任务、好几个状态机或者多个平台的分支给调用了,那处理起来就要非常小心了。这个时候不仅要改代码,还得把回归测试的用例也给补充上。
2、结合着覆盖率去看那些没被执行的调用
TBrun是支持过程调用、语句、分支/判定、MC/DC还有LCSAJ等覆盖指标的,而且它能通过调用图、流程图和文件视图把覆盖的结果展示出来。所以大家可以把调用关系图和覆盖率的结果放到一起去看:要是某条调用链明明存在,但是测试却从来没有执行到过,这时候就要去判断一下,这到底是测试用例缺失了、入口的条件没满足、还是说这条路径本来就不属于现在的配置。
3、关注异常路径以及错误处理的链路
很多调用的缺口并不存在于正常的流程里面,而是在错误返回、超时处理、通信失败或者初始化失败这类分支当中。调用图可以帮开发人员把错误从哪里返回、被谁处理、以及是不是继续往上传递给看清楚。如果错误处理函数很长时间都没被执行到,大家就得去设计一些桩函数让它返回失败、把边界输入构造出来,或者在集成测试里面把对应的场景触发一下。
总结
对于Testbed调用关系怎么查看,以及Testbed调用关系图不完整怎么排查这两个问题,大家可以按照一个先后顺序来处理:先要把工程的解析配置给弄好,然后再从函数或者文件的入口去把调用关系看一看,接着结合着源代码和覆盖率的结果来进行核对。调用关系图并不是一个单独拿来“看结构”的图片,它更适合被放到代码审查、影响分析、覆盖率补测和问题追踪里面一起去使用,这样才能发挥出实际的价值。