Go 博客

Fuzzing 已准备好进入 Beta 测试

Katie Hockman 和 Jay Conrod
2021年6月3日

我们很高兴地宣布,原生 Fuzzing 功能已在 tip 版本中准备好进行 Beta 测试!

Fuzzing 是一种自动化测试,它通过不断地修改程序的输入来查找 panic 或 bug 等问题。这些半随机的数据变异可以发现现有单元测试可能遗漏的新代码覆盖率,并揭示否则会被忽略的边缘情况 bug。由于 Fuzzing 可以触及这些边缘情况,因此 Fuzz 测试对于发现安全漏洞和弱点特别有价值。

有关此功能的更多详细信息,请参阅 golang.org/s/draft-fuzzing-design

入门

要开始,您可以运行以下命令

$ go install golang.org/dl/gotip@latest
$ gotip download

这会从 master 分支构建 Go 工具链。运行此命令后,gotip 可以直接替代 go 命令。您现在可以运行类似以下的命令

$ gotip test -fuzz=Fuzz

编写 Fuzz 测试

Fuzz 测试必须位于 `*_test.go` 文件中,并声明为一个名为 FuzzXxx 的函数。此函数必须接受一个 *testing.F 参数,这与传递给 TestXxx 函数的 *testing.T 参数类似。

下面是一个测试 net/url 包 的 Fuzz 测试示例。

//go:build go1.18
// +build go1.18

package fuzz

import (
    "net/url"
    "reflect"
    "testing"
)

func FuzzParseQuery(f *testing.F) {
    f.Add("x=1&y=2")
    f.Fuzz(func(t *testing.T, queryStr string) {
        query, err := url.ParseQuery(queryStr)
        if err != nil {
            t.Skip()
        }
        queryStr2 := query.Encode()
        query2, err := url.ParseQuery(queryStr2)
        if err != nil {
            t.Fatalf("ParseQuery failed to decode a valid encoded query %s: %v", queryStr2, err)
        }
        if !reflect.DeepEqual(query, query2) {
            t.Errorf("ParseQuery gave different query after being encoded\nbefore: %v\nafter: %v", query, query2)
        }
    })
}

您可以在 pkg.go.dev 上阅读更多关于 Fuzzing 的信息,包括 Go Fuzzing 概览以及 新的 testing.F 类型的 godoc

预期

这是一个仍处于 Beta 阶段的新功能,因此您可能会遇到一些 bug 和不完善的功能。请查看 标记为“fuzz”的 issue 跟踪器,以了解现有 bug 和缺失功能的最新信息。

请注意,Fuzzing 会消耗大量内存,并且在运行时可能会影响您机器的性能。go test -fuzz 默认会在 $GOMAXPROCS 个进程中并行运行 Fuzzing。您可以通过在 go test 命令中显式设置 -parallel 标志来降低 Fuzzing 时使用的进程数量。如果您想了解更多信息,请运行 gotip help testflag 来阅读 go test 命令的文档。

另外请注意,Fuzzing 引擎在运行时会将扩展测试覆盖率的值写入 $GOCACHE/fuzz 目录下的 Fuzz 缓存。目前对写入 Fuzz 缓存的文件数量或总字节数没有限制,因此它可能会占用大量存储空间(例如,数 GB)。您可以通过运行 gotip clean -fuzzcache 来清除 Fuzz 缓存。

下一步是什么?

此功能将从 Go 1.18 开始提供。

如果您遇到任何问题或有功能建议,请提交 issue

有关该功能的讨论和一般反馈,您还可以参与 Gophers Slack 中的#fuzzing 频道

祝您 Fuzzing 愉快!

下一篇文章:Go 在 Stack Overflow 上的集合
上一篇文章:Go 开发者调查 2020 结果
博客索引