mirror of https://github.com/golang/go.git
187 lines
3.8 KiB
Go
187 lines
3.8 KiB
Go
// Copyright 2021 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package fuzz
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestUnmarshalMarshal(t *testing.T) {
|
|
var tests = []struct {
|
|
in string
|
|
ok bool
|
|
}{
|
|
{
|
|
in: "int(1234)",
|
|
ok: false, // missing version
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
string("a"bcad")`,
|
|
ok: false, // malformed
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
int()`,
|
|
ok: false, // empty value
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
uint(-32)`,
|
|
ok: false, // invalid negative uint
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
int8(1234456)`,
|
|
ok: false, // int8 too large
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
int(20*5)`,
|
|
ok: false, // expression in int value
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
int(--5)`,
|
|
ok: false, // expression in int value
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
bool(0)`,
|
|
ok: false, // malformed bool
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
byte('aa)`,
|
|
ok: false, // malformed byte
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
byte('☃')`,
|
|
ok: false, // byte out of range
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
string("has final newline")
|
|
`,
|
|
ok: true, // has final newline
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
string("extra")
|
|
[]byte("spacing")
|
|
`,
|
|
ok: true, // extra spaces in the final newline
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
float64(0)
|
|
float32(0)`,
|
|
ok: true, // will be an integer literal since there is no decimal
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
int(-23)
|
|
int8(-2)
|
|
int64(2342425)
|
|
uint(1)
|
|
uint16(234)
|
|
uint32(352342)
|
|
uint64(123)
|
|
rune('œ')
|
|
byte('K')
|
|
byte('ÿ')
|
|
[]byte("hello¿")
|
|
[]byte("a")
|
|
bool(true)
|
|
string("hello\\xbd\\xb2=\\xbc ⌘")
|
|
float64(-12.5)
|
|
float32(2.5)`,
|
|
ok: true,
|
|
},
|
|
{
|
|
in: `go test fuzz v1
|
|
float32(-0)
|
|
float64(-0)
|
|
float32(+Inf)
|
|
float32(-Inf)
|
|
float32(NaN)
|
|
float64(+Inf)
|
|
float64(-Inf)
|
|
float64(NaN)
|
|
math.Float64frombits(9221120237041090560)
|
|
math.Float32frombits(2143289343)`,
|
|
ok: true,
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.in, func(t *testing.T) {
|
|
vals, err := unmarshalCorpusFile([]byte(test.in))
|
|
if test.ok && err != nil {
|
|
t.Fatalf("unmarshal unexpected error: %v", err)
|
|
} else if !test.ok && err == nil {
|
|
t.Fatalf("unmarshal unexpected success")
|
|
}
|
|
if !test.ok {
|
|
return // skip the rest of the test
|
|
}
|
|
newB := marshalCorpusFile(vals...)
|
|
if err != nil {
|
|
t.Fatalf("marshal unexpected error: %v", err)
|
|
}
|
|
if newB[len(newB)-1] != '\n' {
|
|
t.Error("didn't write final newline to corpus file")
|
|
}
|
|
before, after := strings.TrimSpace(test.in), strings.TrimSpace(string(newB))
|
|
if before != after {
|
|
t.Errorf("values changed after unmarshal then marshal\nbefore: %q\nafter: %q", before, after)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkMarshalCorpusFile measures the time it takes to serialize byte
|
|
// slices of various sizes to a corpus file. The slice contains a repeating
|
|
// sequence of bytes 0-255 to mix escaped and non-escaped characters.
|
|
func BenchmarkMarshalCorpusFile(b *testing.B) {
|
|
buf := make([]byte, 1024*1024)
|
|
for i := 0; i < len(buf); i++ {
|
|
buf[i] = byte(i)
|
|
}
|
|
|
|
for sz := 1; sz <= len(buf); sz <<= 1 {
|
|
sz := sz
|
|
b.Run(strconv.Itoa(sz), func(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
b.SetBytes(int64(sz))
|
|
marshalCorpusFile(buf[:sz])
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkUnmarshalCorpusfile measures the time it takes to deserialize
|
|
// files encoding byte slices of various sizes. The slice contains a repeating
|
|
// sequence of bytes 0-255 to mix escaped and non-escaped characters.
|
|
func BenchmarkUnmarshalCorpusFile(b *testing.B) {
|
|
buf := make([]byte, 1024*1024)
|
|
for i := 0; i < len(buf); i++ {
|
|
buf[i] = byte(i)
|
|
}
|
|
|
|
for sz := 1; sz <= len(buf); sz <<= 1 {
|
|
sz := sz
|
|
data := marshalCorpusFile(buf[:sz])
|
|
b.Run(strconv.Itoa(sz), func(b *testing.B) {
|
|
for i := 0; i < b.N; i++ {
|
|
b.SetBytes(int64(sz))
|
|
unmarshalCorpusFile(data)
|
|
}
|
|
})
|
|
}
|
|
}
|