第18节 go 模糊测试
❤️💕💕Go语言高级篇章,在此之前建议您先了解基础和进阶篇。Myblog:http://nsddd.top
Go语言基础篇
Go语言100篇进阶
[TOC]
Why you need it?
提示
对测试进行一部分的增强,我们平常写代码后肯定需要一部分的单元测试,在原有基础上增强。
测试源
💡简单的一个案例如下:
package main
import "fmt"
func reverse[T string](s T) T {
b := []byte(s)
for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
b[i], b[j] = b[j], b[i]
}
return T(b)
}
func main() {
fmt.Println("反转之前:", "hello")
fmt.Println("反转之后:", reverse("hello"))
fmt.Println("反转之前:", "hello welcome to golang")
fmt.Println("反转之后:", reverse("hello welcome to golang"))
}
🚀 编译结果如下:
[Running] go run "c:\Users\smile\Desktop\test\fuzz-demo\reverse.go"
反转之前: hello
反转之后: olleh
反转之前: hello welcome to golang
反转之后: gnalog ot emoclew olleh
需要测试
我们测试过上面的字符串是没有问题的,但是怎么知道测试其他的内容会不会出现问题呢?
我们需要单元测试:reverse_test.go
package main
import "fmt"
func Reverse[T string](s T) T {
b := []byte(s)
for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
b[i], b[j] = b[j], b[i]
}
return T(b)
}
func main() {
fmt.Println("反转之前:", "hello")
fmt.Println("反转之后:", Reverse("hello"))
fmt.Println("反转之前:", "hello welcome to golang")
fmt.Println("反转之后:", Reverse("hello welcome to golang"))
}
🚀 编译结果如下:
补充
按理说我们只需要 go test
就可以执行测试用例,但是我们报错:
directory . is contained in a module that is not one of the workspace modules listed in go.work. You can add the module to the workspace using go work use .
# 目录中。包含在不是go.work中列出的工作空间模块之一的模块中。您可以使用go work use将模块添加到工作区。
我们如果要使用 go work
下的测试,我们需要加入到工作区:
go work use .\fuzz-demo\
⚠️ 如果是工作区,我们可以直接在工作区测试:
go test mszlu.com/fuzz-demo
PS C:\Users\smile\Desktop\test\fuzz-demo> go test
--- FAIL: TestReverse (0.00s)
reverse_test.go:27: reverse("abc!def12321fedcba") == "abcdef12321fed!cba", want "abc!def12321fedcba"
FAIL
exit status 1
FAIL nsddd.top/fuzz-demo 0.235s
是的,我留下了一个小bug,我们试着解决它:
{"abc!def12321fedcba", "abcdef12321fed!cba"},
🚀 编译结果如下:
PS C:\Users\smile\Desktop\test\fuzz-demo> go test
PASS
ok nsddd.top/fuzz-demo 0.274s
:::
问题
即使我们看起来万无一失,但是实际上还是有个问题,当我们输入中文的时候,我们知道此时的byte[]
是很弱鸡的~
💡简单的一个案例如下:
package main
import (
"fmt"
"testing"
)
func test() {
fmt.Println("这是fuzz-demo的reverse_test.go")
}
func TestReverse(t *testing.T) {
testcases := []struct { //定义一个结构体数组
in, want string //分别是输入和期望输出
}{
{"hello", "olleh"},
{"hello welcome to golang", "gnalog ot emoclew olleh"},
{"", ""},
{"a", "a"},
{"ab", "ba"},
{"abc!", "!cba"},
{"abc!def12321fedcba", "abcdef12321fed!cba"},
{"我是中国人", "人中国是我"},
}
for _, c := range testcases {
got := reverse(c.in)
if got != c.want {
t.Errorf("reverse(%q) == %q, want %q", c.in, got, c.want)
}
}
}
💡简单的一个案例如下:
PS C:\Users\smile\Desktop\test\fuzz-demo> go test
--- FAIL: TestReverse (0.00s)
reverse_test.go:28: reverse("我是中国人") == "\xba\xba佛學䯘摈\xe6", want "人中国是我"
FAIL
exit status 1
FAIL nsddd.top/fuzz-demo 0.264s
警告
当然,我们的目的不仅仅是为了解决它,而是说明我们的测试方法或许可以改进;
我们可能写不了那么多的测试用例,那么我们可以使用模糊测试了
模糊测试
💡简单的一个案例如下:
package main
import (
"fmt"
"testing"
"unicode/utf8"
)
func test() {
fmt.Println("这是fuzz-demo的reverse_test.go")
}
func TestReverse(t *testing.T) {
testcases := []struct { //定义一个结构体数组
in, want string //分别是输入和期望输出
}{
{"hello", "olleh"},
{"hello welcome to golang", "gnalog ot emoclew olleh"},
{"", ""},
{"a", "a"},
{"ab", "ba"},
{"abc!", "!cba"},
{"abc!def12321fedcba", "abcdef12321fed!cba"},
// {"我是中国人", "人中国是我"},
}
for _, c := range testcases {
got := Reverse(c.in)
if got != c.want {
t.Errorf("reverse(%q) == %q, want %q", c.in, got, c.want)
}
}
}
func FuzzReverse(f *testing.F) {
// ...这是模糊测试的代码
// 添加测试集
testcases := []string{"hello", "hello world", "hello welcome to golang", " ", "123124"}
for _, c := range testcases {
//添加测试集
f.Add(c)
}
f.Fuzz(func(t *testing.T, a string) {
got := Reverse(a)
inRevers := Reverse(got) //反转两次,应该和原来的一样(a == inRevers)
if got == inRevers {
t.Errorf("reverse(%q) == %q, want %q", a, got, a)
}
if utf8.ValidString(a) && !utf8.ValidString(got) {
t.Errorf("Reverse produced invalid UTF-8 string: %q", got)
}
})
}
🚀 编译结果如下:
执行方法
执行所有 Fuzz 开头的模糊测试:
go test -fuzz=Fuzz # 执行所有 Fuzz 开头的模糊测试
PS C:\Users\smile\Desktop\test\fuzz-demo> go test -fuzz=Fuzz
--- FAIL: TestReverse (0.00s)
reverse_test.go:29: reverse("我是中国人") == "\xba\xba佛學䯘摈\xe6", want "人中国是我"
FAIL
exit status 1
FAIL nsddd.top/fuzz-demo 0.268s