第45条
使用模糊测试让潜在bug无处遁形
在Go 1.5版本发布的同时,前英特尔黑带级工程师、现谷歌工程师Dmitry Vyukov发布了Go语言模糊测试工具go-fuzz。在GopherCon 2015技术大会上,Dmitry Vyukov在其名为“Go Dynamic Tools”的主题演讲中着重介绍了go-fuzz。
对于模糊测试(fuzz testing),想必很多Gopher比较陌生,当初笔者也不例外,至少在接触go-fuzz之前,笔者从未在Go或其他编程语言中使用过类似的测试工具。根据维基百科的定义,模糊测试就是指半自动或自动地为程序提供非法的、非预期、随机的数据,并监控程序在这些输入数据下是否会出现崩溃、内置断言失败、内存泄露、安全漏洞等情况(见图45-1)。
图45-1 模糊测试的定义
模糊测试始于1988年Barton Miller所做的一项有关Unix随机测试的项目。到目前为止,已经有许多有关模糊测试的理论支撑,并且越来越多的编程语言开始提供对模糊测试的支持,比如在编译器层面原生提供模糊测试支持的LLVM fuzzer项目libfuzzer、历史最悠久的面向安全的fuzzer方案afl-fuzz、谷歌开源的面向可伸缩模糊测试基础设施的ClusterFuzz等。
传统软件测试技术越来越无法满足现代软件日益增长的规模、复杂性以及对开发速度的要求。传统软件测试一般会针对被测目标的特性进行人工测试设计。在设计一些异常测试用例的时候,测试用例质量好坏往往取决于测试设计人员对被测系统的理解程度及其个人能力。即便测试设计人员个人能力很强,对被测系统也有较深入的理解,他也很难在有限的时间内想到所有可能的异常组合和异常输入,尤其是面对庞大的分布式系统的时候。系统涉及的自身服务组件、中间件、第三方系统等多且复杂,这些系统中的潜在bug或者组合后形成的潜在bug是我们无法预知的。而将随机测试、边界测试、试探性攻击等测试技术集于一身的模糊测试对于上述传统测试技术存在的问题是一个很好的补充和解决方案。
在本条中,我们就来看看如何在Go中为被测代码建立起模糊测试,让那些潜在bug无处遁形。