<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    讓寫測試的代碼量驟減,你會開始寫測試嗎?

    一顆小胡椒2022-07-20 10:55:37

    模糊測試是一種向程序提供隨機意外的輸入以測試可能的崩潰或者邊緣情況的方法。通過模糊測試可以揭示一些邏輯錯誤或者性能問題,因此使用模糊測試可以讓程序的穩定性和性能都更有保證。

    Go 從1.18 版本開始正式把模糊測試(Go Fuzz)加入到了其工具集中,不再依靠三方庫就能在程序代碼中進行模糊測試。那么為什么要引入模糊測試呢,引入后我們在寫單元測試的時候要有哪些調整呢?

    首先我們來聊聊為什么引入模糊測試。

    為什么引入模糊測試

    大家看文章開頭第一段的解釋,那就是Go官方要引入模糊測試的原因。估計各位看了想要打人,哈,那我就結合個簡單的例子再把上面那段話要表達的意思,用代碼再解釋一遍。

    大家先不考慮什么模糊測試的事兒,就單純給下面這個工具函數寫一個單測,我們該怎么寫。

    func Equal(a []byte, b []byte) bool {
     for i := range a {
      if a[i] != b[i] {
       return false
      }
     }
     return true
    }
    

    這個工具函數將接收兩個字節切片,比較他們的值是否相等。那么為了通過單測測試這個工具函數是否能如預期那樣完成任務,我們就需要提供一些樣本數據,來測試函數的知識結果。

    單元測試怎么寫

    我們在之前Go 單元測試入門中,給大家介紹過表格測試,就是為單測的執行提供樣本數據的,那么這個表格測試該怎么寫呢?這里直接放代碼了,如果對表格測試和各種Go單測知識不了解的可以回看之前的文章:Go單元測試基礎,文末會給出鏈接。

    func TestEqualWithTable(t *testing.T) {
     tests := []struct {
      name   string
      inputA []byte
      inputB []byte
      want   bool
     }{
      {"right case", []byte{'f', 'u', 'z', 'z'}, []byte{'f', 'u', 'z', 'z'}, true},
      {"right case", []byte{'a', 'b', 'c'}, []byte{'b', 'c', 'd'}, false},
     }
     for _, tt := range tests {
      tt := tt
      t.Run(tt.name, func(t *testing.T) {
       if got := Equal(tt.inputA, tt.inputB); got != tt.want {
        t.Error("expected " + strconv.FormatBool(tt.want) + ",  got " +
            strconv.FormatBool(got))
       }
      })
     }
    }
    

    上面這個單元測試使用的兩個樣本數據能讓測試通過,但不代表我們的工具函數就完美無缺了,畢竟這里的兩個樣本都太典型了,如果你把輸入的兩個切片搞的不一樣,工具函數直接就index out of range,程序直接掛掉了。

    如果沒有模糊測試呢,我們就需要在表格測試里盡量多的提供樣本,才能測出各種邊界情況下程序是否符合預期。

    不過讓自己提供樣本測試,主觀性太強,有的人能想到很多邊界條件有的就不行,再加上我國互聯網公司程序員糟糕的職場生存環境,又要保證BUG少穩定,又要快,這個時候模糊測試確實能幫助我們節省很多想樣本的工作量。

    用模糊測試簡化

    現在我們換用Go 1.18 的 Fuzz 模糊測試,來測試下我們的工具函數。

    func FuzzEqual(f *testing.F) {
     //f.Add([]byte{'a', 'b', 'c'}, []byte{'a', 'b', 'c'})
     f.Fuzz(func(t *testing.T, a []byte, b []byte) {
      Equal(a, b)
     })
    }
    

    雖然模糊測試是1.18 新引入的,但只是節省了我們寫表格測試提供樣本的流程,其他流程和以前的單元測試并不差別,所用到的知識也沒有變化。

    可以看到使用模糊測試后,代碼量明顯減少了很多。模糊測試會幫我們生產隨機的輸入,來供要測試的目標來使用。上面兩個參數的輸入是隨機產生的(也有規則,模糊測試會先測各種空輸入,這個規則我們可以不用管)

    也可以通過f.Add()方法添加語料,注意這里語料設置的個數和順序要和目標函數里的輸入參數保持一致(就是除了 testing.T之外的參數)

    此外還有點明顯的差異大家一定要注意,使用模糊測試后,測試函數的聲明跟普通單測的不一樣

    // 普通單元測試
    TestXXX(t *testing.T){}
    // 使用模糊測試的測試函數,必須以Fuzz開頭,形參類型為*testing.F
    FuzzXXX(f *testing.F) {}
    

    執行模糊測試

    模糊測試執行的時候需要給 go test加上-fuzz這個標記。

    ?  go test -fuzz .
    warning: starting with empty corpus
    fuzz: elapsed: 0s, execs: 0 (0/sec), new interesting: 0 (total: 0)
    fuzz: minimizing 57-byte failing input file
    fuzz: elapsed: 0s, minimizing
    --- FAIL: FuzzEqual (0.04s)
       --- FAIL: FuzzEqual (0.00s)
           testing.go:1349: panic: runtime error: index out of range [0] with length 0
    

    執行模糊測試后,就能測出我上面說的索引越界的問題,這個時候我們就可以回去完善我們的工具函數,然后再進行模糊測試了,通過幾輪執行,會讓被測試的函數足夠健壯。

    我們示例的工具函數足夠簡單,所以修復起來也超簡單,價格長度判斷就可以了。

    func Equal(a []byte, b []byte) bool {
     if len(a) != len(b) {
      return false
     }
     for i := range a {
      if a[i] != b[i] {
       return false
      }
     }
     return true
    }
    

    再度執行模糊測試后程序不再會報錯,不過這個時候你應該發現,測試程序會一直執行,除非主動停下來,或者發現了測試失敗的情況才能讓模糊測試終止。

    這就是模糊測試和普通單測的另一個大區別了,普通單測執行完我們提供的 Case 后就會停止,而模糊測試是會不停的跑樣本,直到發生測試失敗的情況才會停止。這個時候我們就可以用命令指定一個測試時長,讓模糊測試到時自動停止。

    go test -fuzz=Fuzz -fuzztime=10s  .
    

    這里我們通過 fuzztime 這個標志,給模糊測試指定了 10 s的測試時長,到時模糊測試就會自動停止。

    ?  go test -fuzz=Fuzz -fuzztime=10s  .
    fuzz: elapsed: 0s, gathering baseline coverage: 0/10 completed
    fuzz: elapsed: 0s, gathering baseline coverage: 10/10 completed, now fuzzing with 8 workers
    fuzz: elapsed: 3s, execs: 852282 (284056/sec), new interesting: 0 (total: 10)
    fuzz: elapsed: 6s, execs: 1748599 (298745/sec), new interesting: 0 (total: 10)
    fuzz: elapsed: 9s, execs: 2653073 (301474/sec), new interesting: 0 (total: 10)
    fuzz: elapsed: 10s, execs: 2955038 (274558/sec), new interesting: 0 (total: 10)
    PASS
    ok      golang-unit-test-demo/fuzz_test_demo    11.783s
    ?  fuzz_test_demo git:(master) ? 
    

    怎么寫好一個模糊測試

    相信通過上面的例子,其實大家已經看到模糊測試該怎么編寫。為了讓內容更吸引人,文章并沒有上來就給大家羅列一堆名稱概念,這里我們再把理論上的一些東西補充一下,這樣未來自己編寫模糊測試的時候自己心里就更有譜啦。

    模糊測試的結構

    下面是官方文檔里,給出的一張 "模糊測試構成元素" 的圖

    模糊測試的結構,來自:https://go.dev/doc/fuzz/

    這張圖里能看出來這幾點:

    • Fuzz test: 即整個模糊測試函數,它的函數簽名要求,函數名必須以關鍵字 Fuzz 開頭,只有一個類型為*testing.F的參數,且沒有返回值。
    • 模糊測試也是測試,所以跟單測一樣,必須位于_test.go文件中,可以語單測在統一文件。
    • Fuzz Target:模糊測試中,由 f.Fuzz 指定的要執行的測試函數叫 fuzz target,一個模糊測試中只能包含一個 fuzz target,且它的第一個參數必須是*testing.T類型的,后面跟至少一個模糊參數,這個也好理解,如果沒有這個參數,那隨機輸入該往哪輸入呢。
    • Fuzz argument:這個一條說過了,就是fuzz target 中第一個參數以后的參數都叫模糊參數,用來接收模糊測試隨機生成的樣本,這個參數數量應該是要跟我們的被測函數的形參數一致的。
    • Seed corpus:語料,這個單詞兒我也沒見過,大家記住就是提供了它后,生產的隨機參數都跟這個語料有相關性,不是瞎隨機的,且用 f.Add 設置的語料個數,要跟模糊參數的個數、順序、類型上保持一致。

    更詳細的解釋,請參考官方文檔:https://go.dev/doc/fuzz/

    總結

    模糊測試對于檢測我們看不到或想不到的錯誤、邊界情況很有用,即使我們的常規測試具有出色的覆蓋率,話說,諸位,你們的測試覆蓋率真的很出色嗎,還是說完全沒有測試,嘿。

    還有一點要注意的是,模糊測試期間比較耗內存,所以假如想在CI 流水線里加入模糊測試的運行時,需要考量一下資源耗費的問題,定一個適合的運行時長。

    模糊理論
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    2008年在安全社區中所知道的windows惡意可執行軟件大約有1000多萬個,2013年這個數字達到了1億,2020年安全社區已知的windows惡意可執行軟件數量已經超過5億[1],這個數字還在持續增長。
    物聯網被認為是繼計算機、互聯網之后,世界信息產業發展的第三次浪潮。與云計算相比,邊端融合計算可以大大提升物聯網場景下大數據的處理效率,減輕云端負荷,為用戶提供更快的響應,將需求在邊緣側解決。作為更靠近海量數據源的新型計算模式,邊端融合計算逐漸受到越來越多的關注。然而,邊端融合計算在助力物聯網、工業互聯網發展應用的同時,其網絡邊緣高度動態異構的復雜架構會導致邊端融合系統難以保護,帶來終端安全風險滲透
    然而,這些個體特征往往在滿足程序特定條件以到達深層次的程序位置方面發揮關鍵作用。相似度分數包括語法相似性得分、語義相似性得分、稀有度相似性得分。表示種子組覆蓋中那些罕見路徑覆蓋轉換的集合。CLUSTER 函數定義為其中dmax表示種子與所有種子組計算得到的最高相似性分數。當dmax超過γ值時,argmax 函數返回得分為dmax的種子組。湯普森抽樣根據觀察到的獎勵建立概率模型,并從相應模型中采樣每個老虎機的期望值,以選擇下一輪的老虎機。
    正因如此,WebAssembly 指令有時候被稱為虛擬指令。模糊測試AFL模糊測試是一種軟件測試技術。模糊測試常常用于檢測軟件或計算機系統的安全漏洞。陣陣的雷暴在線路上造成噪音,這些噪音又導致兩端的UNIX命令獲得錯誤的輸入,并導致崩潰。作為一名科學家,他想探究該問題的嚴重程度及其原因。最后Fuzzm對AFL進行了高度優化,因此可以在wasm虛擬機上對程序進行模糊測試。
    模糊測試是一種向程序提供隨機意外的輸入以測試可能的崩潰或者邊緣情況的方法。通過模糊測試可以揭示一些邏輯錯誤或者性能問題,因此使用模糊測試可以讓程序的穩定性和性能都更有保證。Go 從1.18 版本開始正式把模糊測試加入到了其工具集中,不再依靠三方庫就能在程序代碼中進行模糊測試。為什么引入模糊測試大家看文章開頭第一段的解釋,那就是Go官方要引入模糊測試的原因。
    網絡安全的發展和創新演進是十分復雜的過程,表現為理論、方法、框架、技術、產品、算法等多種能力升級迭代,涉及用戶、安全廠商、IT廠商、研究機構和政府等多類主體,包含對抗、供需、監管、合作、競爭、共享等多種復雜關系。
    卡巴斯基實驗室的研究人員發現,OPC UA 協議中存在大量漏洞,理論上這些漏洞被利用后會對工業環境帶來物理損害。卡巴斯基實驗室的研究人員對 OPC UA 進行詳細的分析后表示,某些漏洞可被利用發起遠程代碼執行和 DoS 攻擊。 OPC 基金會已發布公告,將這些漏洞歸在兩個漏洞編號下:CNNVD-201712-202(CVE-2017-17433)和 CNNVD-201708-1273(CVE-20
    安全區域邊界在近幾年變得越來越精細越來越模糊,因為攻擊的形式、病毒傳播的途徑層出不窮,我以攻擊者的角度去看,任何一個漏洞都可以成為勒索病毒傳播和利用的方式,我們要做到全面補丁壓力重重,通過邊界劃分,依靠不同的邊界安全防護,在發生問題的情況下將損失降到最低。
    一顆小胡椒
    暫無描述
      亚洲 欧美 自拍 唯美 另类