KUnit 和断言

作者:Zack Brown

KUnit 最近的使用和开发量都在增加。它是内核新的单元测试系统,由 Brendan Higgins 于去年年底引入。其目标是使维护人员和其他开发人员能够以可靠且可重现的方式测试内核代码的离散部分。这与依赖于整个系统行为的各种形式的测试不同,因此,不一定总是产生相同的结果。

最近,Brendan 提交了补丁,使 KUnit 能够方便地与“断言”一起工作。断言类似于条件语句,但它们用于只有一种可能条件应该为真的情况。断言不应该可能为假。因此,如果断言为假,则会触发某种处理程序,开发人员随后使用该处理程序来帮助调试失败背后的原因。

单元测试和断言在某种程度上是相互对立的——当意图是练习被测试的代码时,单元测试可能会触发断言。同样,如果单元测试确实触发了断言,则可能意味着单元测试所做的基本假设无法被依赖,因此测试本身可能无效。

鉴于此,Brendan 提交了 KUnit 代码,以便在触发断言时能够跳出给定的测试。这背后的想法是,断言使测试无效,KUnit 应该毫不浪费时间,而是继续执行队列中的下一个测试。

这个计划没有什么特别有争议的地方。有争议的部分是当 Frank Rowand 注意到 Brendan 在指示单元测试中止但未能中止时,包含了一个对 BUG() 的调用。这种情况永远不应该发生,所以 Brendan 认为在其中是否调用 BUG() 并没有太大的区别。

但是 Frank 说,“如果您提交这个,您只会惹恼 Linus。” 他指出,BUG() 是一种产生内核崩溃并使整个系统挂起的方法。在 Linux 中,这几乎从来都不是解决任何问题的可接受方案。

起初,Brendan 只是耸耸肩,因为在他看来,KUnit 是内核测试基础设施的一部分,因此,永远不会在生产系统上使用。它仅供开发人员使用。在这种情况下,他推断,在朋友之间这里那里有一个 BUG() 有什么区别呢?更不用说,正如他所说,产生 BUG() 调用的条件永远不应该出现。

但是,Frank 说这还不够好。他说,无论您是否认为 KUnit 属于或不属于生产系统,它几乎肯定会在现实世界的生产系统中找到自己的位置。事情就是这样发展的。人们会做不推荐的事情。但是,即使情况并非如此,Frank 说,非生产系统也同样应该避免调用 BUG(),除非崩溃系统是避免实际数据损坏的唯一方法。

Brendan 对放弃调用 BUG() 没有认真的反对意见,他只是提出问题,因为似乎有什么问题很奇怪。但是,他很乐意放弃它。

因此,该功能仍然保留,而错误处理将发生变化。关于这场特殊辩论的一个有趣之处在于,它突出了内核的许多调试和错误处理方面可能出现的各种冲突。各种冲突和竞争条件都可能出现。

例如,开发人员可能会编写一个新的驱动程序,并希望测试它在重负载下的行为。因此,他们将在使用其驱动程序时运行内存密集型进程,却发现内核的内存溢出 (OOM) 杀手在驱动程序内触发关键测试情况之前就杀死了生成负载的进程。

考虑到 Linux 内核开发过程的每个方面都镶嵌着如此大量的测试和调试功能,这真是令人惊叹。甚至 git 本身,这个由 Linus Torvalds 专门为托管内核开发而创建的版本控制系统,本身也是一个调试工具,它确保可以识别并可能回滚那些最终导致问题的更改。除了所有其他内容之外,还有各种各样的自动化系统在各种私营企业内运行。其中一些系统加载运行特定工作负载的系统;有些系统直接读取源代码,寻找模式。不可能知道 Linux 内核每天接收到的测试的完整种类和程度。

注意:如果您在上面被提及并希望在评论区上方发布回复,请将您的回复文本发送消息至 ljeditor@linuxjournal.com。

Zack Brown 是 Linux JournalLinux Magazine 的技术记者,并且是 “Kernel Traffic” 每周新闻通讯和 “Learn Plover” 速记打字教程的前作者。他于 1993 年首次在他的 386 电脑上安装了 Slackware Linux,配备 8MB 内存,并被开源社区彻底震撼。他是纯策略棋盘游戏 Crumble 的发明者,您可以用几块纸板自己制作。他还喜欢写小说、尝试动画、改革拉班舞谱、设计和缝制自己的衣服、学习法语以及与朋友和家人共度时光。

加载 Disqus 评论