'lit' it
如果你一直在关注 LLVM 和 Clang,你就会注意到我们正在使用一个叫做 **lit** 的新的测试工具。Clang 已经迁移到它,而 LLVM 也支持它(DejaGNU 仍然是默认值,但正在逐步淘汰)。我写这篇文章是为了说明一下我为什么要编写 **lit**,它是什么,以及它将如何让你的生活更美好。:)
首先,让我总结一下 **lit** 之前的背景
- LLVM 使用了 DejaGNU 和 googletest 单元测试。不过,我们对 DejaGNU 的使用非常有限,我们真正使用的是一种测试格式,它在每个测试文件中嵌入 shell 脚本。我们的 DejaGNU 框架会解释这些命令,替换一些变量,运行它们,并检查退出状态。googletest 单元测试是单独运行的,而且经常被遗忘。
- Clang 使用了类似但完全不同的基础设施,它仍然嵌入 shell 脚本,但通过 **make** 和 **sed** 运行它们。它具有并行运行测试和显著简化的显著优势,但不是特别灵活。
这两个系统有一个共同点,那就是添加一个新的测试非常容易,通常只需在适当的目录中添加一个文件中的几行代码。但有一些恼人的缺点
- 无法通过 CMake 或在 Windows 上运行测试。
- LLVM 测试没有并行运行。
- 测试的 UI 不一致且繁琐(尤其是对于 DejaGNU,它需要通过 shell 脚本调用 LLVM Makefile,然后调用 DejaGNU 的 runtest 命令)。
我实际上并没有打算写一个新的测试工具 - **lit** 的诞生是因为我需要运行大量的“测试”,这只是一个固定脚本,需要用许多不同的输入运行。我为它快速地编写了一个多线程 Python 测试运行器,随着时间的推移,它添加了进度条和更多功能。后来,当人们越来越希望 Clang 在 Windows 上运行时,我为这些脚本编写了一个基于 Python 的解释器(记住,它们只是 shell 脚本,所以 **lit** 里面隐藏了一个小型的 (ba) **sh** 词法分析器和解析器)。将这两者结合起来并不断添加新功能并不需要太多想象力,直到它能够取代 DejaGNU(是的,它还有一个微小的 Tcl 解析器)。
那么,**lit** 究竟是什么呢?严格来说,**lit** 是一个测试运行基础设施,比如 DejaGNU。它的主要任务是找到测试,执行它们,并将结果报告给用户;它碰巧内置了对 LLVM 和 Clang 测试格式的支持。我的首要设计目标是 **lit** 应该尽可能地“正常工作” - 运行测试应该像这样简单
$ lit exprs.s
lit: lit.cfg:94: note: using out-of-tree build at '/Volumes/Data/ddunbar/llvm.obj.64'
-- Testing: 1 tests, 2 threads --
PASS: LLVM::MC/AsmParser/exprs.s (1 of 1)
Testing Time: 0.06s
Expected Passes : 1
无论你是在使用树内还是树外构建,是在测试 Clang 还是 LLVM,是在进行回归测试还是基于 googletest 的单元测试,是在 Windows 还是 Unix 上,等等。当然,我还希望它速度快!
我不会详细介绍如何使用 **lit**(因为它应该是不言自明的或者有文档),但以下是一些我们从切换到 **lit** 中获得的功能和好处
- LLVM 测试运行得更快,如果我没记错的话,这让我们在快速机器上的 buildbot 构建/测试周期提高了大约 25%。我仍然有一个秘密愿望,那就是让它们更快……总有一天……
- Clang 测试可以在 Windows 上运行,并且已经整合到我们的 buildbot 中。LLVM 测试还需要做一些工作。
- LLVM/Clang 测试可以在 CMake 构建中运行(使用 Makefiles、Xcode 和 Visual Studio 生成器)。
- **lit** 与 buildbot 整合得很好,因此单个错误会分解成各自的日志。我希望继续改进诊断错误的 UI。
- 基于 LLVM googletest 的单元测试与其他测试无缝集成。事实上,当使用标准 LLVM Makefiles 时,你可能只需使用以下命令就能运行所有 LLVM 和 Clang 测试make check-all.
- 我们正在使用一些更高级的 **lit** 功能来帮助进行 C++ 测试。例如,我们有自定义的测试套件,它们会运行clang -fsyntax-only在 libstdc++ 和 LLVM/Clang 头文件上,以测试解析器,或者运行clang -c在 LLVM 和 Clang C++ 代码上,以测试 Clang 的 C++ 代码生成。我私底下怀疑 Doug 在他的硬盘驱动器上隐藏了更多的 **lit** 测试套件。
- 我还有更多改进正在进行中……
- Daniel
附注:**lit** 代表 LLVM 集成测试器,至少这是我公开宣称的。或者,它是我想到的第一个可以发音的三个字母的名称……