GO 1.18新特性 (一) — 模糊测试 (Fuzzing Test)

2022年3月27日 291点热度 0人点赞 0条评论

Go 1.17 发布七个月后,Go 1.18 正式发布了! Go 1.18 是一个包含大量新功能及新特性的版本,包括对语言本身做了有史以来最大的改变。其中最值得关注的新特性包括:范型,Fuzzing TestWorkspace

接下来我会带大家一起来快速感受一下GO 1.18的新特性。

什么是模糊测试?

模糊测试是对Go原有测试包的一个扩充,它是一种自动化测试。通过随机生成输入数据来测试程序,用于尝试被程序员忽略的测试条件。甚至通过模糊测试可以找到的一些漏洞示例包括 SQL 注入、缓冲区溢出、拒绝服务和跨站点脚本攻击。

直接上例子

这里直接借用了Go官方文章中的例子(https://go.dev/doc/tutorial/fuzz)

package examples
import ( "testing" "unicode/utf8")
// 被测试方法func Reverse(s string) string { b := []byte(s) for i, j := 0, len(b)-1; i < len(b)/2; i, j = i+1, j-1 { b[i], b[j] = b[j], b[i] } return string(b)}
// Fuzz测试func FuzzReverse(f *testing.F /* 注意:这里是testing.F */) { /* 种子测试数据 */ testcases := []string{"Hello, world", " ", "!12345"} for _, tc := range testcases { f.Add(tc) // Use f.Add to provide a seed corpus } f.Fuzz(func(t *testing.T, orig string) { rev := Reverse(orig) doubleRev := Reverse(rev) if orig != doubleRev { t.Errorf("Before: %q, after: %q", orig, doubleRev) } if utf8.ValidString(orig) && !utf8.ValidString(rev) { t.Errorf("Reverse produced invalid UTF-8 string %q", rev) } })}

模糊测试程序编写要点:

  • 测试函数以Fuzz开头,  参数为testing.F

  • f.Add 为添加种子测试数据,Fuzz测试将通过对种子测试数据进行随机变化而产生新的测试数据。(可以没有种子测试数据,直接生成随机测试数据)

  • f.Fuzz 的来运行fuzz测试,这个函数的参数是 func (t testing.T, … /*测数据类型列表*/) 。

运行测试程序:

通过命令行 go test -fuzz=. 来运行,这里与运行benchmark测试十分类似。

测试程序会一直运行下去,直到产生错误(触发测试失败的条件)或者运行时间超时,可以通过-fuzztime参数来指定超时时长。

导致测试失败的随机数据会被记录到 testdata/fuzz/FuzzReverse/路径下的文件中。并且该数据在我们再次运行测试时会被自动加入到种子测试数据中。

另,go test也可以运行Fuzz开头的测试函数,但是仅仅只会运行种子测试数据 (包括,我们上面提到的加入到种子数据中的失败case的数据)

注意事项

1. 目前模糊测试支持的随机测试数据类型:

  • string, []byte

  • int, int8, int16, int32/rune, int64

  • uint, uint8/byte, uint16, uint32, uint64

  • float32, float64

  • bool

2. 要保证Fuzz测试快速且具有确定性,以便测试引擎可以高效工作及轻松重现故障。

3.为了加快测试的速度,fuzz测试会通过并发的方式来执行,所以测试的实现中不应该依赖于任何共享状态。(测试执行的并发度/工作协程数可以通过 命令行参数-parallel来设置,默认值为$GOMAXPROCS)

思考

验证断言可以说是测试的灵魂。但由于测试数据是随机生成的,所以编写模糊测试时的验证断言并不像普通单元测试这样中容易写。

例如上面的例子中:

对于普通测试,如果输入数据是给定的,如:“hello”, 我们可以断言 Reverse (input) == “olleh”。而对于模糊测试,我们就无法这样简单的断言了,上面的测试中采用了 Reverse(Reverse(input)) == input 这样的巧妙方式。

很多时候,这样的测试验证断言是很难设计的,当然最基本的我们可以判断是否产生错误。

以上只是对该特性的简单介绍,更多内容大家可以参考官方文档学习。

图片

73220GO 1.18新特性 (一) — 模糊测试 (Fuzzing Test)

这个人很懒,什么都没留下

文章评论