From b0e7e87e08f04c7de5ac835225dc06efc89da2b0 Mon Sep 17 00:00:00 2001 From: asahi Date: Thu, 9 Jan 2025 01:43:35 +0800 Subject: [PATCH] =?UTF-8?q?=E9=98=85=E8=AF=BBunit=20test=E5=92=8Cfuzz=20te?= =?UTF-8?q?st=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Golang/Golang Document.md | 119 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/Golang/Golang Document.md b/Golang/Golang Document.md index e083bfd..4b7a81c 100644 --- a/Golang/Golang Document.md +++ b/Golang/Golang Document.md @@ -191,3 +191,122 @@ fmt.Printf("Generic Sums with Constraint: %v and %v\n", SumNumbers(ints), SumNumbers(floats)) ``` +## Fuzzing +如下为一个反转字符串的示例: +```go +package fuzz + +func Reverse(str string) (ret string, err error) { + bytes := []byte(str) + for i, j := 0, len(bytes)-1;i 在编写fuzz test时,可以将unit test, fuzz test, benchmark都包含在同一个`_test.go`文件中 + +在编写fuzz test方法时,步骤如下 +- fuzz test方法以`FuzzXxx`开头,和`TestXxx`类似 +- 当调用`f.Add`时,会将参数作为seed添加 + +Fuzz test示例如下: +```go +func FuzzReverse(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 test +在编写完上述代码后,首先应该执行`go test`命令,确保作为seed被添加的cases能够通过测试 +```bash +go test +``` + +> 如果,只想执行指定的测试方法,可以指定`-run`参数,示例如下 +> +> ```bash +> go test -run=FuzzReverse +> ``` + +在`go test`执行通过之后,应该执行`go test -fuzz=Fuzz`命令,其会将随机产生的输入作为测试。 + +如果存在随机生成的用例测试不通过,会将该用例写入到seed corups文件中,`在下次go test命令被执行时,即使没有指定-fuzz选项,被写入文件中的用例也会被在此执行`。 + +> 当通过`go test -fuzz=Fuzz`执行fuzz test时,测试会一直进行,直到被`Ctrl + C`中断。 +> +> 如果要指定fuzz test的时间,可以指定`-fuzztime`选项。 +> +> 示例如下: +> ```bash +> go test -fuzz=Fuzz -fuzztime 30s +> ``` + +fuzz test的输出结果示例如下: +```powershell +PS D:\CodeSpace\demo\fuzz> go test -fuzz=Fuzz -fuzztime 10s +fuzz: elapsed: 0s, gathering baseline coverage: 0/56 completed +fuzz: elapsed: 0s, gathering baseline coverage: 56/56 completed, now fuzzing with 32 workers +fuzz: elapsed: 3s, execs: 3028153 (1008398/sec), new interesting: 2 (total: 58) +fuzz: elapsed: 6s, execs: 6197524 (1057429/sec), new interesting: 2 (total: 58) +fuzz: elapsed: 9s, execs: 9423882 (1075420/sec), new interesting: 2 (total: 58) +fuzz: elapsed: 10s, execs: 10482150 (926639/sec), new interesting: 2 (total: 58) +PASS +ok git.kazusa.red/asahi/fuzz-demo 10.360s +``` +> #### new interesting +> `new interesting`指会扩充code coverage的用例输入,在fuzz test刚开始时,new interesting数量通常会因发现新的代码路径快速增加,然后,会随着时间的推移逐渐减少 +