返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

12.3 模糊测试

发布于 2024-10-12 19:15:50 字数 3721 浏览 0 评论 0 收藏 0

又称随机测试,一种基于随机输入发现代码缺陷的自动化测试技术。

  • 对单元测预定数据的补充,查找未预料错误。
  • 并非验证逻辑正确,而是发现输入处理缺陷。
  • 保存在 _test.go 内。
  • 函数名以 Fuzz 为前缀。
  • 类型 FT 方法类似,省略。
  • 初始数据,称作 种子语料 (seed corpus)。
  • 基于种子构造的随机数据,称作 随机语料 (random corpus)。
func FuzzAdd(f *testing.F) {
    
    // 添加种子。(可选)
	f.Add(1, 1)
	f.Add(1, 2)
	f.Add(1, 3)

    // 随机测试。(第一参数为 *T,后续和测试目标函数相同)
	f.Fuzz(func(t *testing.T, x, y int) {
		add(x, y)
	})
}

默认被当作普通单元测试运行。测试数据就是种子,不会引入随机语料。

$ go test -v ./mylib

=== RUN   FuzzAdd
=== RUN   FuzzAdd/seed#0
=== RUN   FuzzAdd/seed#1
=== RUN   FuzzAdd/seed#2

--- PASS: FuzzAdd (0.01s)
    --- PASS: FuzzAdd/seed#0 (0.00s)
    --- PASS: FuzzAdd/seed#1 (0.00s)
    --- PASS: FuzzAdd/seed#2 (0.00s)
    
PASS
ok      test/mylib      0.011s

只有添加 -fuzz 参数才会进行随机测试。
默认无限期执行,直到失败或被用户中断( CTRL + C )。

  • -fuzz : 测试目标。(regex)
  • -fuzztime : 时长或次数。( 1m20s , 100x
$ go test -v -fuzz Add -fuzztime 20s ./mylib

=== FUZZ  FuzzAdd

fuzz: elapsed: 0s, gathering baseline coverage: 0/3 completed
fuzz: elapsed: 0s, gathering baseline coverage: 3/3 completed, 2 workers

fuzz: elapsed:  3s, execs:  28786 (9594/sec),  new interesting: 0 (total: 3)
fuzz: elapsed:  6s, execs:  62406 (11205/sec), new interesting: 0 (total: 3)
fuzz: elapsed:  9s, execs:  93140 (10245/sec), new interesting: 0 (total: 3)
fuzz: elapsed: 12s, execs: 125159 (10671/sec), new interesting: 0 (total: 3)
fuzz: elapsed: 15s, execs: 158390 (11079/sec), new interesting: 0 (total: 3)
fuzz: elapsed: 18s, execs: 191887 (11164/sec), new interesting: 0 (total: 3)
fuzz: elapsed: 20s, execs: 214470 (10858/sec), new interesting: 0 (total: 3)

--- PASS: FuzzAdd (20.09s)
PASS
ok      test/mylib      20.092s

模糊测试基于 “覆盖引导”(coverage guidance)。

start with some (potentially empty) corpus of inputs

for {
    choose a random input from the corpus
    mutate the input
    execute the mutated input and collect code coverage
    if the input gives new coverage, add it to the corpus
}

基线覆盖率(baseline coverage)是对现有语料(种子等)的测试结果,提供基准指标。
执行期间,如某条随机输入导致语料库之外的覆盖率变化,那么可称作 “new interesting”。

" new interesting " 保存在 GOCACHE/fuzz 目录下,可被 go clean -fuzzcache 清除。

  • elapsed :启动时间。
  • execs :模糊输入总数。
  • new interesting :引发覆盖率变化的输入数,以及语料库总数。

引发失败的原因:

  • panic
  • t.Fail ...
  • os.Exit , stack overflow ...
  • 目标执行时间过长(默认 1 秒)。

语料库

除在代码中添加种子外,还可以将其存储在文件内,自动载入。

  • 路径testdata/fuzz/<FuzzName>/
  • 文件 :每个文件保存一组语料,也就是一次 Add 调用的参数。
$ cat mylib/testdata/fuzz/FuzzAdd/a
go test fuzz v1
int(1)
int(1)

$ cat mylib/testdata/fuzz/FuzzAdd/b
go test fuzz v1
int(1)
int(2)

$ cat mylib/testdata/fuzz/FuzzAdd/c
go test fuzz v1
int(1)
int(3)

测试出错时,也会将随机输入存储到该路径下。
作为回归测试的基准语料,以检查目标是否被修复。

Failing input written to testdata/fuzz/FuzzAdd/3cb146f923...828c
    To re-run:
    go test -run=FuzzAdd/3cb146f923...828c

Go Fuzzing

Fuzzing support for Go

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文