代码添加LCOV代码覆盖率处理共需要以下步骤:
一、确保代码交叉编译选项增加了lcov处理 ---> gcno文件生成
A、编译增加 “-fprofile-arcs-ftest-coverage” 选项
此处我们直接在基础编译选项中增加-fprofile-arcs -ftest-coverage选项,对应的实现方式是在…/SCUN1_OF-AGENT_SPTN/plat/jobs/linux_ppc/buildinit.cfg文件中的COMPILE_BASE_OPTS变量增加。
LCOV_TYPE:= -fprofile-arcs -ftest-coverage
COMPILE_BASE_OPTS = $(BUILD_OPTS) $(BEP) -DVOS_CPU=PPC -DVOS_LINUX-DPOSIX_THREAD_SEMANTICS -DREENTRANT -D IPCOM_BASE -D NBB_RELEASE_ASSERT-c $(LCOV_TYPE)
B、增加链接过程中的lcov库
在…/SCUN1_OF-AGENT_SPTN/dev/linux_ppc/dev_cr8000/jobs/makefile 文件中的LIBFILE 变量中,增加- lgcov
export LIBFILE =-lporttranis -lDBEP -ldl -ldb-4.2 -lxml2 -lapp -leos –lgcov
至此我们完成了lcov交叉编译选项的添加,进入编译目录执行编译脚本
在编译文件后,可以发现对应的gcno文件已经生成。以SPTN的ofp模块为例,其产生的gcno文件位于如下目录(其他模块类似) …./SCUN1_OF-AGENT_SPTN/plat/jobs/linux_ppc/p2/release/obj/ofp下
二、gcda 文件生成
将上一步在编译服务器上编译好的包,拷贝到设备中去
A、更新ofagt的包文件至当前上传的版本
1)、ps aux |grep of 找到设备当前运行的ofagt的进程号
2)、kill -9PID 关掉ofagt进程
3)、在/mnt/nand 目录下rm –rfofagt 删除掉原有的ofagt 目录(此处删除是为了防止后续解压时出现覆盖)
4)、在/mnt/nand 目录下 tar –jxvfofagt-201712281101-701460-release-p1020.tbz 解压程序包
B、ofagtEntry.sh替换
在/mnt/nand 目录下 mkdirgcda 以创建gcda文件存储目录
ofagtEntry.sh 脚本中,在ofagt进程启动前,增加一下两项,以便进程kill时能够产生gcda文件
exportGCOV_PREFIX_STRIP=4
exportGCOV_PREFIX="/mnt/nand/gcda"
注:此步骤目前SPTN中已在编译步骤实现
C、进行各项单元测试
尽可能多的去测试相关项,尤其是修改的代码部分处理,以增加代码覆盖
D、结束进程
采用 kill -11 PID 的方式结束掉ofagt的进程(此处使用kill 的那种信号,需要根据进程中实际所注册的信号处理来定),这样会在/mnt/nand/gcda目录下生成gcda文件
至此我们完成了gcda文件的生成处理。此时我们可以在设备的/mnt/nand/gcda目录下发现一个plat文件夹,将整个gcda文件夹拷贝出来。仍然以ofp部分为例,可以查看到产生的相应gcda文件
将gcda文件夹拷贝至编译服务器的 …/SCUN1_OF-AGENT_SPTN目录下
三、LCOV覆盖率计算
1、在gcda文件夹下增加lcov覆盖率计算处理脚本,并赋予该脚本可执行权限;
#!/bin/sh
PWD="$(pwd)"
echo $PWD
VERSION=release
BUILD_DIR=/home/baiqishi/work/SCUN1_OF-AGENT_SPTN
USR_DIR=$BUILD_DIR/gcda/plat/jobs/linux_ppc/p2/$VERSION/obj
SRC_DIR=$BUILD_DIR/plat
OBJ_DIR=$BUILD_DIR/plat/jobs/linux_ppc/p2/$VERSION/obj
# calculate the percent of coverity
msg(){
echo "==========================================="
echo "0、./calculate_lcov.sh -> for all app models"
echo "1、./calculate_lcov.sh ofp -> for ofp models"
echo "2、./calculate_lcov.sh tne -> for tne models"
echo "==========================================="
}
calculate_all(){
#==========================================================
# 0、all model, contain ofp、tneagt、fhsi、dap
#==========================================================
if [ -d ofagt_lcov ] ; then
echo "Clear the lcov dir for ofagt"
rm -rf ofagt_lcov
fi
echo "=== Create the lcov dir for ofagt ==="
mkdir ofagt_lcov
cd $USR_DIR
if [ -d ofagt_temp ] ; then
echo "Clear the lcov dir for ofagt_temp"
rm -rf ofagt_temp
fi
mkdir ofagt_temp
cp $SRC_DIR/ofp/*.c $USR_DIR/ofp
cp $OBJ_DIR/ofp/*.gcno $USR_DIR/ofp
cp $USR_DIR/ofp/* $USR_DIR/ofagt_temp
cp $SRC_DIR/tneagt/*.c $USR_DIR/tneagt
cp $OBJ_DIR/tneagt/*.gcno $USR_DIR/tneagt
cp $USR_DIR/tneagt/* $USR_DIR/ofagt_temp
cp $SRC_DIR/fhsi/*.c $USR_DIR/fhsi
cp $OBJ_DIR/fhsi/*.gcno $USR_DIR/fhsi
cp $USR_DIR/fhsi/* $USR_DIR/ofagt_temp
cp $SRC_DIR/dpa/*.c $USR_DIR/dpa
cp $OBJ_DIR/dpa/*.gcno $USR_DIR/dpa
cp $USR_DIR/dpa/* $USR_DIR/ofagt_temp
lcov --capture --directory $USR_DIR/ofagt_temp --output-file $BUILD_DIR/gcda/ofagt_lcov/test.info --gcov=powerpc-wrs-linux-gnu-gcov --test-name test
genhtml $BUILD_DIR/gcda/ofagt_lcov/test.info --output-directory $BUILD_DIR/gcda/ofagt_lcov/output --title asimpletest --show-details --legend
}
calculate_ofp(){
#==========================================================
# 1、ofp model
#==========================================================
if [ -d ofp_lcov ] ; then
echo "Clear the lcov dir for ofp"
rm -rf ofp_lcov
fi
echo "=== Create the lcov dir for ofp ==="
mkdir ofp_lcov
cp $SRC_DIR/ofp/*.c $USR_DIR/ofp
cp $OBJ_DIR/ofp/*.gcno $USR_DIR/ofp
lcov --capture --directory $USR_DIR/ofp --output-file ./ofp_lcov/test.info --gcov=powerpc-wrs-linux-gnu-gcov --test-name test
genhtml ./ofp_lcov/test.info --output-directory ./ofp_lcov/output --title asimpletest --show-details --legend
}
calculate_tne(){
#==========================================================
# 2、tneagt model
#==========================================================
if [ -d tne_lcov ] ; then
echo "Clear the lcov dir for tne"
rm -rf tne_lcov
fi
echo "=== Create the lcov dir for tne ==="
mkdir tne_lcov
cp $SRC_DIR/tneagt/*.c $USR_DIR/tneagt
cp $OBJ_DIR/tneagt/*.gcno $USR_DIR/tneagt
lcov --capture --directory $USR_DIR/tneagt --output-file ./tne_lcov/test.info --gcov=powerpc-wrs-linux-gnu-gcov --test-name test
genhtml ./tne_lcov/test.info --output-directory ./tne_lcov/output --title asimpletest --show-details --legend
}
if [ ! -d plat ]; then
echo "There is no gcda files! EXIT"
exit
fi
if [ $# = 0 ]; then
echo "CALCULATE ALL MODELS!"
calculate_all
elif [ $# = 1 ]; then
if [ $1 = "ofp" ]; then
echo "CALCULATE OFP MODELS!"
calculate_ofp
elif [ $1 = "tne" ];then
echo "CALCULATE TNE MODELS!"
calculate_tne
else
echo "CALCULATE PARAMS ERROR!!!"
msg
fi
else
echo "CALCULATE PARAMS ERROR!!!"
msg
fi
LCOV主要是以下两条指令:
lcov --capture--directory ofagt_temp --output-file test.info--gcov=powerpc-wrs-linux-gnu-gcov --test-name test
genhtml test.info--output-directory output--title asimpletest --show-details –legend
2、根据编译产生的执行文件版本为debug / release ,修改calculate_lcov.sh脚本相应配置;
3、执行calculate_lcov.sh 脚本以计算代码覆盖率情况
./calculate_lcov.sh #计算整个ofagt的lcov
./calculate_lcov.sh ofp #计算ofp模块的lcov
./calculate_lcov.sh tneagt #计算tneagt模块的lcov
以ofp模块为例,进行lcov覆盖率计算处理后,计算的结果信息会存储在gcda目录下的ofp_lcov文件夹中
通过查看output文件夹下的index.html可以查看当前的ofp模块代码覆盖率情况。
注:必须确保在设备中运行的程序为当前所编译出来的最新的版本,如果设备中所运行的不是当前最新编译产生的将会无法进行相应的覆盖率的计算处理。
附:unitTesting 工具计算增量代码的覆盖率
通过上述LCOV处理后,计算得到的是全量代码的覆盖率情况,如果我们仅仅计算增量代码的覆盖率情况的话,需要进一步执行如下操作处理。
注:此处我们采用SVN作为代码版本管理,使用unitTesting 工具来进行代码增量覆盖率的计算。会使用到SVN命令行,如果没有安装SVN命令行则需要安装。
1、将前面由LCOV计算得到的output文件夹拷贝至../UnitTest/example目录下
2、调用windows的cmd命令行窗口,进入到unitTesting工具所在的目录下执行
unitTestingcfgfile.txt
3、至此会得到代码增量的覆盖率情况,计算得到的增量代码覆盖率会存在
../UnitTest/localunitTesting/Debug/test目录下的result.txt文档中