Go 部落格
Fuzzing 已準備好進入 Beta 測試
我們很高興地宣佈,原生 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 結果
部落格索引