Go语言精进之路:从新手到高手的编程思想、方法和技巧(2)
上QQ阅读APP看书,第一时间看更新

45.5 让模糊测试成为“一等公民”

go-fuzz的成功和广泛应用让Gopher认识到模糊测试对挖掘潜在bug、提升代码质量有着重要的作用。但目前Go尚未将模糊测试当成“一等公民”对待,即还没有在Go工具链上原生支持模糊测试,模糊测试在Go中的应用还仅限于使用第三方的go-fuzz或谷歌开源的gofuzz。

但当前的go-fuzz等工具的实现存在一些无法解决的问题[1],比如:

  • go-fuzz模仿Go工具构建逻辑,一旦Go原生工具构建逻辑发生变化,就会导致go-fuzz-build不断损坏;
  • go-fuzz-build无法处理cgo,很难实现;
  • 目前的代码覆盖率工具(coverage)是通过在源码中插入桩代码实现的,这使其很难与其他构建系统(build system)集成;
  • 基于从源码到源码的转换无法处理所有情况,并且转换功能有限,某些代码模式可能会处理不当或导致构建失败;
  • 使用从源码到源码转换的方法产生的代码运行很慢。

这些问题需要编译器层面的支持,也就是在编译器层面添加支持模糊测试的基础设施(比如代码覆盖率桩的插入)。同时,如果模糊测试能像go test、go test -bench那样直接通过Go工具链执行(比如go test -fuzz=.),模糊测试代码能像普通单元测试代码那样直接编写在*_test.go文件中,像下面这样:

// xxx_test.go

func FuzzXxx(f *testing.F, data []byte) {
    // ...
}

那么模糊测试才算真正得到了“一等公民”的地位,这一直是模糊测试在Go语言中的努力方向。目前Go官方已经在讨论将模糊测试纳入Go工具链的实现方案了(https://github.com/golang/go/issues/19109)。

小结

通过这一条,我们认识到模糊测试对于提升Go代码质量、挖掘潜在bug的重要作用。但模糊测试不是“银弹”,它有其适用的范围。模糊测试最适合那些处理复杂输入数据的程序,比如文件格式解析、网络协议解析、人机交互界面入口等。模糊测试是软件测试技术的一个重要分支,与单元测试等互为补充,相辅相成。

目前,并非所有编程语言都有对模糊测试工具的支持,Gopher和Go社区很幸运,Dmitry Vyukov为我们带来了go-fuzz模糊测试工具。如果你是追求高质量Go代码的开发者,请为你的Go代码建立起模糊测试。


[1]https://github.com/golang/go/issues/14565