Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > Go fuzz模糊测试

Go中的fuzz模糊测试使用实战详解

作者:Go学习日记

这篇文章主要为大家介绍了Go中的fuzz模糊测试使用实战详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言

软件系统越复杂,测试就越重要。然而手动测试可能会非常费时和乏味。这就是为什么自动化测试变的越来越流行的原因。今天我们来聊一聊自动化测试中的一种测试技术就是fuzz测试,它是一种随机测试技术,可以帮助发现软件系统中的漏洞和错误。

Go语言目前已经是非常流行的语言了,具有高效、并发等特性。今天我们浅谈使用Go语言进行fuzz测试。从Go1.18开始,Go在其标准工具链中支持模糊测试。

什么是fuzz测试

模糊测试 (fuzz testing, fuzzing)是一种软件测试技术。其核心思想是将自动或半自动生成的随机数据输入到一个程序中,并监视程序异常,如崩溃,断言(assertion)失败,以发现可能的程序错误,比如内存泄漏。模糊测试常常用于检测软件或计算机系统的安全漏洞。

Go语言中的模糊测试

Go为开发者提供了一套强大的工具,用于实施模糊测试,核心是testing包中的Fuzz函数。通过创建以Fuzz为前缀的函数,按特定的签名定义输入输出,可以很容易集成模糊测试到我们的Go程序中。

上图是一个模糊测试的例子,突出显示了它的主要组件。

模糊测试必须要遵循的规则:

Fuzz测试的参数类型只能是以下类型:

string, []byte

int, uint, uintptr, int8, int16, int32, rune, int64, uint8, uint16, uint32, uint64

float32, float64

bool

这些规则和要求是Go语言fuzz测试的基本要求,遵循这些规则可以帮助我们编写有效的fuzz测试并提高测试覆盖率。

接下来我们通过一些简单代码来体验一下Fuzz test。

代码编写

我们创建一个名为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))
}

运行代码

go run .
Add(1, 2) = 3

现在代码正常运行,接下来我们来测试它。

添加单元测试

我们先为Add函数编写一个基本的单元测试。

贴如以下代码到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)
		}
	}
}

执行单元测试

> go test -v

=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
PASS
ok      example/fuzz    0.003s

添加模糊测试

单元测试的局限是我们必须把每个输入添加到测试中,模糊测试的好处是它提供了你的代码,并且可能识别你想出的测试用例的边缘情况。

我们把add_test.go中的单元测试替换为以下内容模糊测试。

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)
	})
}

接下来我们执行模糊测试, 通过-run选项用于指定要运行的测试函数的正则表达式,-fuzz选项用于指定要运行的fuzz测试函数的正则表达式,-fuzztime选项来控制fuzz测试的持续时间。

> 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

总的来说,Go语言内置的fuzz测试框架提供了一种方便的方式来进行fuzz测试,它与testing包紧密集成,可以更方便的进行单元测试和fuzz测试。

以上就是Go中的fuzz模糊测试使用实战详解的详细内容,更多关于Go fuzz模糊测试的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文