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