SAVE: 软件分析验证和测试平台
一个长期困扰软件分析研究人员的现实问题是缺乏统一的测试框架和测试用例集。本文将介绍面向软件分析工具的新型CI生态系统SAVE (Software Analysis Verification and Evaluation)。SAVE的目的是提供一个统一的软件分析验证和测试平台,为验证和对比软件分析工具提供方便。SAVE目前主要有以下功能:
- 提供一个统一的测试验证框架,方便在本地验证软件分析工具的功能;
- 提供一个统一的平台,用户可以根据已经集成的常见测试套或者自行上传测试套来对比不同软件分析工具的有效性,或者评估其适用范围;
- 提供了REST API,可以将测试验证集成到软件分析工具的开发流程中(如CI/CD)。
不久的将来,SAVE还将支持社区举办软件分析技术相关的竞赛。
一. 动机
我们团队的一个重要工作是研发面向开发者、提高开发效率和质量的静态分析工具,包括缺陷检查与修复、开源组件风险识别、三方库冲突识别等。为验证工具的有效性,需要搭建一个面向此类工具的测试框架和平台,看护静态分析工具的演进过程,综合评估静态分析工具的能力和效率。而现状是每个静态分析工具都在一遍又一遍地搭建自己专用的测试框架。
我们对多个开源静态分析工具的测试框架进行了调研,目前使用最广的是LLVM Lit[1]。其他框架存在能力受限、开源社区不够活跃、关注面窄等问题。LLVM Lit是面向LLVM生态工具(如Clang、LLVM backend、CSA等)的测试框架。但经过调研,我们发现LLVM Lit一些缺点,主要有:
- Lit由一些Python脚本组成,难以做到免安装随时执行;
- Lit设计的时候是面向编译器的,且没有考虑到应用逻辑上的可扩展性;
- Lit由社区系统开发者创造,只是一个简单的CLI工具,没有形成生态系统
此外,缺陷检查工具的开发者大都面临着类似的问题:怎么评估工具的有效性?目前公认的测试用例集是NIST[2]。但NIST并没有提供测试平台,让开发者能更直观地看到工具演进情况以及与同类工具相比怎么样。此外,NIST中的测试用例也主要是人为构造的,难以用来评估检查工具的实际效果。
抱着改变目前的状况、为软件分析从业者提供便利的想法,我们开发了SAVE框架(SAVE-cli[3])和服务(SAVE-cloud[4])。软件分析工具的开发者不用再重复开发测试框架、可以复用已有测试用例集来测试工具的有效性。
实际上,软件分析工具测试场景是相似的,使得构建统一的测试框架成为可能。常见测试场景如下:
- 将字符串形式的源代码传递给分析工具;
- 分析工具以黑盒子的形式来执行内部的分析逻辑;
- 分析工具输出结果:代码中间表示如AST、静态检查告警、修复后的代码、代码执行结果等。所有的输出数据都可以用字符串形式表示。
二. SAVE-cli
2.1 命令行应用
SAVE-cli是一个简单的本地命令行应用,可以用来测试分析工具的功能。SAVE是一个统一的框架,不依赖特定的生态系统(如JVM、Python)。用户只需要按照SAVE格式来写测试用例即可,不需要考虑其他事情。
我们还提供了类似于插件的接口使得SAVE-cli具有可扩展性。每个人都可以创建自己的插件。目前我们已经有了Fix和Warn两个插件。
2.2 插件介绍
Fix插件[5]。该插件运行在原始测试文件上运行工具,并将输出与预期结果进行对比。我们使用我们构建的diff library[6]来完成对比功能。
Warn插件[7]。该插件比较有意思的地方是提供了一个易于阅读和用户友好的DSL来验证常见的静态分析工具告警。可以在测试用例源码中使用DSL来描述期望的告警信息。该DSL支持正则、多行告警。下面是一个具体的例子。
2.3 资源检测机制
SAVE-cli实现了递归资源检测机制。为了让SAVE能够检测到测试套,用户需要配置save.toml文件,包括测试套名字,描述信息等。并将该文件放在存放测试用例的目录。SAVE支持多级配置,底层的配置会继承上一层的配置。例如,对于下面的目录层级,目录B中的save.toml会自动继承目录A的配置。
| A | save.toml | B | save.toml |
SAVE遵循一个测试套一个save.toml配置文件的规则。换言之,只有哪些包含save.toml文件的目录才会被SAVE当做测试用例来处理。SAVE会自动检测目录中以Test结尾的文件将被作为测试资源,并使用处在同样目录的save.toml文件作为测试配置。
| A | save.toml | B <<< test suite | myTest.java <<< test resource | save.toml |
三. SAVE-cloud
3.1 有哪些新特性?
大型工程的测试用例较多,例如gcc和clang有超过50万的测试用例。想象一下,这种情况下,CI处理速度将会慢成什么样?考虑到这些测试用例往往是相互独立的,利用云计算的分批并发处理机制可以有效提高测试效率。SAVE-cloud就是这样一个基于云计算的测试框架,包含如下特性:
- 统一的测试框架;
- 云CI平台来执行测试任务;
- 测试结果可视化看板;
- 存储历史测试结果;
- 支持回归测试;
- 可用于验证或比较分析工具的Benchmark集合
3.2 SAVE-cloud工作流程
SAVE-cloud利用SAVE-cli测试验证软件分析工具并存储历史结果。其工作流程如下:
- 用户可以使用SAVE-cloud提供的REST API或者WEB界面;
- 用户可以选择已有benchmark或者上传自己的benchmark;
- 触发处理流程,启动一个docker容器,调用SAVE-cli来执行测试;
- 将所有历史执行结果存储在数据库中,方便分析
流程图如下图所示:
3.3 SAVE-cloud怎么用?
SAVE-cloud已经部署在站点https://saveourtool.com。
1. 用户可以点击“Sign in”,此时通过github授权登录。如果之前没有登录过, SAVE将自动创建一个用户。当然,用户也可以点击“Continue”以游客身份访问。
2. 创建或选择一个组织。
3. 创建新的测试项目。可以使用私有git仓。填写基本信息,包括所属组织、受测工具名称、受测工具网址、测试套的git地址、描述信息。为保护隐私,SAVE采用Token的授权方式来访问git仓库。用户还可以选择是否将测试项目公开,如果不公开,该项目将不会出现在看板上,其他人也无法查看。
4. 项目创建之后,可以上传受测工具的二进制文件及其他相关文件(如辅助脚本)。需要注意的是,受测工具执行命令需要配置在toml文件中,见配置项“execCmd”。最后,点击“Test the tool now”来执行测试。
5. 每次执行结果都会记录下来。用户可以在看板上看到历史执行结果,还可以查看每次执行的详细结果。
3.4 SAVE API
SAVE-cloud也提供了REST API,可以方便地集成到各种CI/CD平台,包括GitHub Action、Jenkins、TeamCity等。具体做法可以参考说明文档[8]。
四. 总结
我们希望未来在静态分析领域能有一个统一的基准测试框架和平台。SAVE-cli和SAVE-cloud在此方向迈出了一步,为软件分析领域的研究人员测试验证他们的分析工具提供方便。我们相信SAVE还有很多地方需要改进,还有很多工作可以做,欢迎大家前来试用体验和提供建议。目前SAVE的所有组件都已经开源,诚邀大家一起参与贡献!
文章来自PaaS技术创新Lab; PaaS技术创新Lab隶属于华为云(华为内部当前发展最为迅猛的部门之一,目前国内公有云市场份额第二,全球第五),致力于综合利用软件分析、数据挖掘、机器学习等技术,为软件研发人员提供下一代智能研发工具服务的核心引擎和智慧大脑。我们将聚焦软件工程领域硬核能力,不断构筑研发利器,持续交付高价值商业特性!加入我们,一起开创研发新“境界”!(招聘接口人:guodongshuo@huawei.com)
PaaS技术创新Lab主页链接:https://www.huaweicloud.com/lab/paas/home.html
参考文献:
- LLVM Lit: https://llvm.org/docs/CommandGuide/lit.html
- NIST Juliet Test Suites: https://samate.nist.gov/SARD/test-suites
- SAVE-cli: https://github.com/saveourtool/save-cli
- SAVE-cloud: https://github.com/saveourtool/save-cloud
- SAVE fix plugin: https://github.com/saveourtool/save-cli/blob/main/save-plugins/fix-plugin/README.md
- Diff library: https://github.com/petertrr/kotlin-multiplatform-diff
- SAVE warn plugin: https://github.com/saveourtool/save-cli/blob/main/save-plugins/warn-plugin/README.md
- SAVE API:https://github.com/saveourtool/save-cloud/blob/master/save-backend/Backend-API.md
- 点赞
- 收藏
- 关注作者
评论(0)