github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/internal/fuzz/encoding_test.go (about)

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package fuzz
     6  
     7  import (
     8  	"strconv"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  func TestUnmarshalMarshal(t *testing.T) {
    14  	var tests = []struct {
    15  		in string
    16  		ok bool
    17  	}{
    18  		{
    19  			in: "int(1234)",
    20  			ok: false, // missing version
    21  		},
    22  		{
    23  			in: `go test fuzz v1
    24  string("a"bcad")`,
    25  			ok: false, // malformed
    26  		},
    27  		{
    28  			in: `go test fuzz v1
    29  int()`,
    30  			ok: false, // empty value
    31  		},
    32  		{
    33  			in: `go test fuzz v1
    34  uint(-32)`,
    35  			ok: false, // invalid negative uint
    36  		},
    37  		{
    38  			in: `go test fuzz v1
    39  int8(1234456)`,
    40  			ok: false, // int8 too large
    41  		},
    42  		{
    43  			in: `go test fuzz v1
    44  int(20*5)`,
    45  			ok: false, // expression in int value
    46  		},
    47  		{
    48  			in: `go test fuzz v1
    49  int(--5)`,
    50  			ok: false, // expression in int value
    51  		},
    52  		{
    53  			in: `go test fuzz v1
    54  bool(0)`,
    55  			ok: false, // malformed bool
    56  		},
    57  		{
    58  			in: `go test fuzz v1
    59  byte('aa)`,
    60  			ok: false, // malformed byte
    61  		},
    62  		{
    63  			in: `go test fuzz v1
    64  byte('☃')`,
    65  			ok: false, // byte out of range
    66  		},
    67  		{
    68  			in: `go test fuzz v1
    69  string("has final newline")
    70  `,
    71  			ok: true, // has final newline
    72  		},
    73  		{
    74  			in: `go test fuzz v1
    75  string("extra")
    76  []byte("spacing")  
    77      `,
    78  			ok: true, // extra spaces in the final newline
    79  		},
    80  		{
    81  			in: `go test fuzz v1
    82  float64(0)
    83  float32(0)`,
    84  			ok: true, // will be an integer literal since there is no decimal
    85  		},
    86  		{
    87  			in: `go test fuzz v1
    88  int(-23)
    89  int8(-2)
    90  int64(2342425)
    91  uint(1)
    92  uint16(234)
    93  uint32(352342)
    94  uint64(123)
    95  rune('œ')
    96  byte('K')
    97  byte('ÿ')
    98  []byte("hello¿")
    99  []byte("a")
   100  bool(true)
   101  string("hello\\xbd\\xb2=\\xbc ⌘")
   102  float64(-12.5)
   103  float32(2.5)`,
   104  			ok: true,
   105  		},
   106  	}
   107  	for _, test := range tests {
   108  		t.Run(test.in, func(t *testing.T) {
   109  			vals, err := unmarshalCorpusFile([]byte(test.in))
   110  			if test.ok && err != nil {
   111  				t.Fatalf("unmarshal unexpected error: %v", err)
   112  			} else if !test.ok && err == nil {
   113  				t.Fatalf("unmarshal unexpected success")
   114  			}
   115  			if !test.ok {
   116  				return // skip the rest of the test
   117  			}
   118  			newB := marshalCorpusFile(vals...)
   119  			if err != nil {
   120  				t.Fatalf("marshal unexpected error: %v", err)
   121  			}
   122  			if newB[len(newB)-1] != '\n' {
   123  				t.Error("didn't write final newline to corpus file")
   124  			}
   125  			before, after := strings.TrimSpace(test.in), strings.TrimSpace(string(newB))
   126  			if before != after {
   127  				t.Errorf("values changed after unmarshal then marshal\nbefore: %q\nafter:  %q", before, after)
   128  			}
   129  		})
   130  	}
   131  }
   132  
   133  // BenchmarkMarshalCorpusFile measures the time it takes to serialize byte
   134  // slices of various sizes to a corpus file. The slice contains a repeating
   135  // sequence of bytes 0-255 to mix escaped and non-escaped characters.
   136  func BenchmarkMarshalCorpusFile(b *testing.B) {
   137  	buf := make([]byte, 1024*1024)
   138  	for i := 0; i < len(buf); i++ {
   139  		buf[i] = byte(i)
   140  	}
   141  
   142  	for sz := 1; sz <= len(buf); sz <<= 1 {
   143  		sz := sz
   144  		b.Run(strconv.Itoa(sz), func(b *testing.B) {
   145  			for i := 0; i < b.N; i++ {
   146  				b.SetBytes(int64(sz))
   147  				marshalCorpusFile(buf[:sz])
   148  			}
   149  		})
   150  	}
   151  }
   152  
   153  // BenchmarkUnmarshalCorpusfile measures the time it takes to deserialize
   154  // files encoding byte slices of various sizes. The slice contains a repeating
   155  // sequence of bytes 0-255 to mix escaped and non-escaped characters.
   156  func BenchmarkUnmarshalCorpusFile(b *testing.B) {
   157  	buf := make([]byte, 1024*1024)
   158  	for i := 0; i < len(buf); i++ {
   159  		buf[i] = byte(i)
   160  	}
   161  
   162  	for sz := 1; sz <= len(buf); sz <<= 1 {
   163  		sz := sz
   164  		data := marshalCorpusFile(buf[:sz])
   165  		b.Run(strconv.Itoa(sz), func(b *testing.B) {
   166  			for i := 0; i < b.N; i++ {
   167  				b.SetBytes(int64(sz))
   168  				unmarshalCorpusFile(data)
   169  			}
   170  		})
   171  	}
   172  }