Go中的fuzz模糊測(cè)試使用實(shí)戰(zhàn)詳解
前言
軟件系統(tǒng)越復(fù)雜,測(cè)試就越重要。然而手動(dòng)測(cè)試可能會(huì)非常費(fèi)時(shí)和乏味。這就是為什么自動(dòng)化測(cè)試變的越來(lái)越流行的原因。今天我們來(lái)聊一聊自動(dòng)化測(cè)試中的一種測(cè)試技術(shù)就是fuzz測(cè)試,它是一種隨機(jī)測(cè)試技術(shù),可以幫助發(fā)現(xiàn)軟件系統(tǒng)中的漏洞和錯(cuò)誤。
Go語(yǔ)言目前已經(jīng)是非常流行的語(yǔ)言了,具有高效、并發(fā)等特性。今天我們淺談使用Go語(yǔ)言進(jìn)行fuzz測(cè)試。從Go1.18開(kāi)始,Go在其標(biāo)準(zhǔn)工具鏈中支持模糊測(cè)試。
什么是fuzz測(cè)試
模糊測(cè)試 (fuzz testing, fuzzing)是一種軟件測(cè)試技術(shù)。其核心思想是將自動(dòng)或半自動(dòng)生成的隨機(jī)數(shù)據(jù)輸入到一個(gè)程序中,并監(jiān)視程序異常,如崩潰,斷言(assertion)失敗,以發(fā)現(xiàn)可能的程序錯(cuò)誤,比如內(nèi)存泄漏。模糊測(cè)試常常用于檢測(cè)軟件或計(jì)算機(jī)系統(tǒng)的安全漏洞。
Go語(yǔ)言中的模糊測(cè)試
Go為開(kāi)發(fā)者提供了一套強(qiáng)大的工具,用于實(shí)施模糊測(cè)試,核心是testing
包中的Fuzz
函數(shù)。通過(guò)創(chuàng)建以Fuzz
為前綴的函數(shù),按特定的簽名定義輸入輸出,可以很容易集成模糊測(cè)試到我們的Go程序中。
上圖是一個(gè)模糊測(cè)試的例子,突出顯示了它的主要組件。
模糊測(cè)試必須要遵循的規(guī)則:
Fuzz測(cè)試必須是一個(gè)函數(shù),函數(shù)名必須以"Fuzz"開(kāi)頭,后面必須是一個(gè)大寫(xiě)字母開(kāi)頭的名稱,例如"FuzzAdd"。
Fuzz測(cè)試函數(shù)必須接受一個(gè)*testing.F類型的參數(shù),不能有返回值。
Fuzz測(cè)試函數(shù)必須在*_test.go文件中定義才能運(yùn)行。
Fuzz目標(biāo)必須是一個(gè)方法調(diào)用,第一個(gè)參數(shù)必須是*testing.F類型,后面跟隨著fuzz測(cè)試的參數(shù)。
每個(gè)fuzz測(cè)試函數(shù)只能有一個(gè)fuzz目標(biāo)。
所有的種子語(yǔ)料庫(kù)條目的類型必須與fuzz測(cè)試的參數(shù)類型相同,順序也必須相同。這適用于對(duì)Fuzz函數(shù)的調(diào)用以及fuzz測(cè)試的testdata/fuzz目錄中的任何語(yǔ)料庫(kù)文件。
Fuzz測(cè)試的參數(shù)類型只能是以下類型:
string, []byte
int, uint, uintptr, int8, int16, int32, rune, int64, uint8, uint16, uint32, uint64
float32, float64
bool
這些規(guī)則和要求是Go語(yǔ)言fuzz測(cè)試的基本要求,遵循這些規(guī)則可以幫助我們編寫(xiě)有效的fuzz測(cè)試并提高測(cè)試覆蓋率。
接下來(lái)我們通過(guò)一些簡(jiǎn)單代碼來(lái)體驗(yàn)一下Fuzz test。
代碼編寫(xiě)
我們創(chuàng)建一個(gè)名為fuzz的目錄
> mkdir fuzz > cd fuzz > go mod init example/fuzz > touch main.go
在main.go中我們貼如以下代碼
package main import "fmt" func Add(a, b int) int { return a + b } func main(){ fmt.Printf("Add(1, 2) = %d\n", Add(1, 2)) }
運(yùn)行代碼
go run . Add(1, 2) = 3
現(xiàn)在代碼正常運(yùn)行,接下來(lái)我們來(lái)測(cè)試它。
添加單元測(cè)試
我們先為Add函數(shù)編寫(xiě)一個(gè)基本的單元測(cè)試。
在
fuzz
目錄創(chuàng)建一個(gè)文件為add_test.go
。
貼如以下代碼到add_test.go
。
package main import "testing" func TestAdd(t *testing.T) { testcases := []struct { a, b, want int }{ {1, 2, 3}, {0, 0, 0}, {-1, -2, -3}, {1, -2, -1}, } for _, tc := range testcases { got := Add(tc.a, tc.b) if got != tc.want { t.Errorf("Add(%d, %d) == %d, want %d", tc.a, tc.b, got, tc.want) } } }
執(zhí)行單元測(cè)試
> go test -v === RUN TestAdd --- PASS: TestAdd (0.00s) PASS ok example/fuzz 0.003s
添加模糊測(cè)試
單元測(cè)試的局限是我們必須把每個(gè)輸入添加到測(cè)試中,模糊測(cè)試的好處是它提供了你的代碼,并且可能識(shí)別你想出的測(cè)試用例的邊緣情況。
我們把a(bǔ)dd_test.go中的單元測(cè)試替換為以下內(nèi)容模糊測(cè)試。
func FuzzAdd(f *testing.F) { f.Add(1, 2) f.Add(0, 0) f.Add(-1, -2) f.Add(-2, -2) f.Fuzz(func(t *testing.T, a, b int) { got := Add(a, b) if got != a+b { t.Errorf("Add(%d, %d) == %d, want %d", a, b, got, a+b) } t.Logf("Add(%d, %d) == %d", a, b, got) }) }
接下來(lái)我們執(zhí)行模糊測(cè)試, 通過(guò)-run
選項(xiàng)用于指定要運(yùn)行的測(cè)試函數(shù)的正則表達(dá)式,-fuzz
選項(xiàng)用于指定要運(yùn)行的fuzz測(cè)試函數(shù)的正則表達(dá)式,-fuzztime
選項(xiàng)來(lái)控制fuzz測(cè)試的持續(xù)時(shí)間。
> go test -v -run=FuzzAdd -fuzz=Fuzz -fuzztime 10s === RUN FuzzAdd fuzz: elapsed: 0s, gathering baseline coverage: 0/11 completed fuzz: elapsed: 0s, gathering baseline coverage: 11/11 completed, now fuzzing with 8 workers fuzz: elapsed: 3s, execs: 718882 (239620/sec), new interesting: 1 (total: 12) fuzz: elapsed: 6s, execs: 1444761 (241916/sec), new interesting: 1 (total: 12) fuzz: elapsed: 9s, execs: 2177414 (244215/sec), new interesting: 1 (total: 12) fuzz: elapsed: 10s, execs: 2415524 (216791/sec), new interesting: 1 (total: 12) --- PASS: FuzzAdd (10.10s) === NAME PASS ok example/fuzz 10.106s
總的來(lái)說(shuō),Go語(yǔ)言內(nèi)置的fuzz測(cè)試框架提供了一種方便的方式來(lái)進(jìn)行fuzz測(cè)試,它與testing包緊密集成,可以更方便的進(jìn)行單元測(cè)試和fuzz測(cè)試。
以上就是Go中的fuzz模糊測(cè)試使用實(shí)戰(zhàn)詳解的詳細(xì)內(nèi)容,更多關(guān)于Go fuzz模糊測(cè)試的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Golang利用位運(yùn)算實(shí)現(xiàn)為程序加速
這篇文章主要為大家詳細(xì)介紹了如何在Golang中利用位運(yùn)算實(shí)現(xiàn)為程序加速功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-08-08Go語(yǔ)言實(shí)現(xiàn)websocket推送程序
這篇文章主要介紹了Go語(yǔ)言實(shí)現(xiàn)websocket推送程序,WebSocket是基于TCP的一個(gè)雙向傳輸數(shù)據(jù)的協(xié)議,和HTTP協(xié)議一樣,是在應(yīng)用層的,他的出現(xiàn),是為了解決網(wǎng)頁(yè)進(jìn)行持久雙向傳輸數(shù)據(jù)的問(wèn)題2023-01-01記一次go語(yǔ)言使用time.Duration類型踩過(guò)的坑
本文主要介紹了記一次go語(yǔ)言使用time.Duration類型踩過(guò)的坑,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01