Android原生底层驱动应用面极广,但一直没有很好的办法进行质量追踪。本文借助星云精准测试的高可靠性的测试技术手段,针对Android原生底层驱动进行分析、插桩、编译、采集数据、数据分析等,逐步讲解精准测试是如何实现android原生底层驱动的对接。
在本文中,我们可以清晰地查看到如何进行技术对接的每一步,比如如何使用星云精准测试进行代码插桩、实现测试用例与采集底层驱动运行代码的数据追溯、对最终采集的数据进行一系列分析等。
一、安卓源码精准测试流程概述
经分析android源码的编译主要依靠Android.bp为纽带连接起来;在编译时,只需要在想要编译的模块目录下执行mm命令即可自动的根据当前目录下的Android.bp文件对其所包含的模块进行编译。
主要流程大致为:先将ZOA通信库源码复制进去并加入某一层次的Android.bp中,再通过对包含所有Android.bp编译信息的ninja文件的解析可以得到Shell认可的插桩json文件,Shell通过json文件对对应目录的代码进行插桩,插桩完成后,把对ZOA通信库的引用加入该模块的Android.bp中再放入ZoaInstru.h头文件后就可以正常编译出插桩程序了。
二、对安卓源码进行精准测试的准备工具
1.安卓原生8.1.0系统源码,放于/data/source2/目录下
2.shell.tar.gz插桩工具包放于/data/目录下
3.ZOAMQLib通信库源码放于/data/source2/ frameworks/av/目录下
4.谷歌官方装有原生8.1.0系统手机一部
本例是对/data/source2/ frameworks/av/camera模块进行插桩编译,首先source build/envsetup.sh配置环境变量,再lunch后输入2选择aosp_arm64-eng,再mm编译模块
三、精准测试插桩工具部署
在存放精准测试插桩工具包的/data/目录下执行命令
tar -zxvf shell.tar.gz
将精准测试插桩工具包解压
cd /data/shell/bin
进入shell包bin目录下打开并修改Server.cfg的[SERVER]字段的ip为星云精准测试服务端ip,对[LOCAL]字段的ip,客户端若与服务端在同一主机则保持127.0.0.1,若在不同主机则写明客户端ip。
四、ZOA通信库加入安卓体系
本次选择av模块进行精准测试的插桩编译验证模块,在对av模块进行深入了解后,解析出其Android,bp的连接其结构大致如此,每一个最终节点就代表会生成一个动态库或者静态库。
av大致结构与ZOA通信库加入安卓体系示意图:
注:由于第二层mediadrm模块库目录过多不便展开,但原理又是相同,所以仅对该模块展示骨架信息;绿色部分代表会产生一个库文件,mediadrm只是骨架结构所以未标识。
本次是将写好对应的Android.bp文件的ZOA通信库源代码目录整个复制到av目录下,并在av目录下的Android.bp文件中加入ZOA通信库的目录。
cd /data/source2/frameworks/av/
进入av模块
vi Android.bp
打开av模块的Android.bp文件,并将ZOAMQLib目录加入其中
ZOA通信库加入av模块的Android.bp图示:
然后在ZOAMQLib目录下直接执行mm命令,编译出安卓体系下的ZOA通信库。
五、插桩编译流程
1.生成json文件
android源码在进行编译时他会将所有的Android.bp中的信息提取出来并添加一些编译信息来生成一个build.ninja文件。该文件中含有编译的模块、源代码和编译参数等信息。
通过android自带的ninja工具可以将该build.ninja文件转化为包含源代码路径、源代码名字和编译参数信息的json文件;再通过工具可以将要插桩模块的部分提取出来生成该模块的插桩json文件
生成json文件的命令:
/data/source2/prebuilts/build-tools/linux-x86/bin/ninja -t compdb g.cc.cc > compile_commands.json
其中/data/source2/为安卓源代码路径
2.插桩代码
shell编译器可以通过该json文件对该模块进行插桩或还原操作。
插桩代码命令 shell的路径/shell -p json文件的路径/ compile_commands.json
还原代码命令 shell的路径/shell -r json文件的路径/ compile_commands.json
本次插桩与还原命令:
/data/shell/bin/shell -p /data/source2/compile_commands.json
/data/shell/bin/shell -r /data/source2/compile_commands.json
插桩成功后在客户端重新加载版本数据:
3.编译链接
链接通信库
cd /data/source2/frameworks/av/camera
进入camera目录下
vi Android.bp
打开camera模块的Android.bp文件并在shared_libs中加入ZOA通信库的名字
camera的Android.bp加入ZOA通信库链接图示:
加入头文件
cp /data/shell/include/ZoaInstru.h /data/source2/frameworks/av/camera/include/
将ZOA的头文件加入被插桩的camera的头文件夹中
然后就可以按照正常的编译流程来进行编译,执行mm编译该模块。
插桩编译图示:
六、测试方式
本例是将安卓原生8.1.0代码进行插桩后,放入谷歌官方8.1.0系统并获得root权限的手机中进行测试
本次插桩的是av模块的camera部分,所以我们将
camera模块库:
/data/source2/out/soong/.intermediates/frameworks/av/camera/libcamera_client/android_arm64_armv8-a_shared_core/libcamera_client.so
ZOA通信库:
/data/source2/out/soong/.intermediates/frameworks/av/ZOAMQLib/libZOAMQLib/android_arm64_armv8-a_shared_core /libZOAMQLib.so
这两个库放进手机的/system/lib64/目录中开机进行相机测试。
测试概念图:
将被测手机开机后用usb线连接到电脑上,采用adb端口映射的方法将程序运行时产生的动态数据传输到星云精准测试工具上,再通过示波器进行波形展示。
数据传输图:
在星云精准测试工具客户端打开示波器界面,建立测试用例并选择测试用例后点击 开始 并对手机进行相机功能的操作就可以在接收到动态数据并示波器看到波形了。
示波器接收数据图:
七、精准测试-基础功能
1.覆盖率
在对测试用例录制完成后就可以在主界面看到覆盖率等相关信息。
在函数列表中随便点开一个函数就可以查看该函数的各项覆盖率。
1.SCO覆盖率
SCO覆盖率即为语句块覆盖率,在函数内顺序执行遇见if、for、while等就算为一个语句块。
SC0覆盖率图示:
2.MCDC覆盖率
MCDC 修订条件判定覆盖,精准测试中对mcdc做了量化展示,分别统计单一条件个数,针对每一个条件判断是否满足mcdc覆盖如果满足如上图绿色表示条件满足mcdc覆盖,蓝色表示不满足。并对MCDC做了详细信息的展示(选择MCDC覆盖,点击判定,显示MCDC的详细信息)
MCDC覆盖率图示:
注:
1.覆盖率信息一共有七种,分别为SCO语句块覆率、True、Flase、Both等条件覆盖率、Branch条件分支覆盖率、CDC条件判定覆盖率、MCDC修正条件判定。
2.精准测试默认是不关联源码的,如需要关联源代码使用,请将源码复制到客户端本地,在版本上右键选择修改源码路径,然后添加源码路径来关联源码。
2.函数调用关系图
函数调用图,只有函数调用的关系,能够比较清楚地看清函数调用的层次关系。当点击其中的某个函数时,能显示以该函数为中心,调用该函数的上三层和下三层调用(可点击设置层级进行层级的调整)。
当接收过动态数据后还能将各项数据显示在图像界面中。
3.程序控制流程图
控制流程图基础功能是展示函数的控制流程,即控制流程图,用于表示函数的控制流程、显示测试覆盖率结果、实现半自动高效率测试用例设计,进行逻辑流程查错,以及源码、测试用例和相关文档之间的双向自动追溯等。
4.简易控制流程图
简易控制流程图功能,以语句块的形式清晰的展示函数内部的控制逻辑,界面上可以直观的看出控制流各节点的测试覆盖情况,在展示中,简易控制流程图还可以通过颜色对每个程序块进行覆盖率标识,在缩略图中整个模块的覆盖率非常直观。(背景色为绿色表示有测试用例覆盖到该块)关联源码后点击语句块可定位到代码具体行。
5.双向追溯
由于精准测试的测试用例与执行过的函数绑定,可以在测试台通过选择不同的测试用例来正向追溯找到它执行过的函数;或者通过选择不同的函数或代码来反向追溯找到执行过它的测试用例。
正向追溯图示:
该正向追溯是通过在左上侧选择测试用例来在下方展示该测试用例运行过的函数
反向追溯图示:
反向追溯既可以通过左下角的函数来追溯运行过该函数的测试用例,还可以通过选择代码块来追溯运行过该块的测试用例。
八、精准测试-高级分析功能
1.智能回归测试用例选取
在第一个版本测试完成后对第二个版本进行插桩后就在星云精准测试工具生成了第二个工程版本。此时我们要做的不是立马对新版本进行测试,而是使用我们星云精准测试的回归功能对新插桩的版本进行回归,它会根据版本之间代码的变化的来分析出与该函数相关的测试用例,然后根据测试用例内函数改变的多少进行回归优先级的排序,智能的推荐出需要重新跑的测试用例,以及显示出不需要跑的测试用例。
智能回归示例:
cd /data/source2/frameworks/av/camera进入到camera目录下
vi ICamera.cpp打开该源码进行修改
在getParameters函数中加入if(1==1);条件
然后对camera模块进行插桩,再在客户端使用选取回归测试用例功能进行回归
由于getParameters函数内新增条件发生变化,所以运行过该函数的测试用例的回归计数就加一,然后该测试用例就被推荐出来需要重新去跑一遍。
回归图示:
对精准测试而言,其是采用在测试阶段,将测试用例和它所执行过的函数绑定的方法。在版本迭代时会将上一个版本的测试用例继承下来,通过回归跟上个版本进行比较,哪个函数有了变化,那么与其相关的测试用例的功能都可能会发生变化,所以在回归时会推荐出要重新测试的测试用例;而当一个测试用例里面关联的所有函数都没发生变化时他的功能也不会发生变化,那么此时再去测试一遍该用例是没有意义的事情。所以,在新版本插桩完毕后和以前的进行回归后就可以看出哪些用例需要重新跑哪些完全不用再跑。
2.最后执行时序
该部分是执行插桩程序进行动态数据接收时保存的最后五十个语句块执行的时序关系图
它可以点击每一步次序查看执行块的代码
3.聚类分析
聚类算法中个数的设置是需要手动设置的,一般看颗粒度的粗细进行设置。聚类算法是通过测试用例的代码相似程度得出结果的,所以可以帮助我们划分出来有哪些测试用例的代码相似程度比较高,
本次共设计7个测试用例,两次拍照、两次录视频、一次随便侧、一次打开相机、一次打开相机后闲置。
选择分类个数为5后,聚类结果为:
切换为图形模式为:
10、Web报表
1.覆盖率按日增长曲线图
使用折线图清晰的展现每天该版本覆盖率的变化情况
左下角雷达图展示了预期的各项覆盖率与实际各项覆盖看的差距
右下角对比了当前版本与最新版本各项覆盖率的差异
2.测试漏洞的智能分析
在一个程序中,往往有成百上千的函数,这些函数有的是关联整个程序核心、有的则是开发人员弃而不用,但一直保留迟迟不肯删除的,针对这些大量的函数,“精准测试”采用通过静态、动态指标的综合分析,在大量的程序函数中,通过计算直接筛选潜在的高危的测试漏洞,通过报表给予展示。
当一个函数复杂度很高但覆盖率却很低的时候其出现风险的概率就可能比较高
当函数扇入扇出越大时,意味着其关联函数越多,结合其覆盖率信息也可能是风险较高。