• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5package fuzz
6
7import (
8	"bytes"
9	"testing"
10)
11
12type mockRand struct {
13	values  []int
14	counter int
15	b       bool
16}
17
18func (mr *mockRand) uint32() uint32 {
19	c := mr.values[mr.counter]
20	mr.counter++
21	return uint32(c)
22}
23
24func (mr *mockRand) intn(n int) int {
25	c := mr.values[mr.counter]
26	mr.counter++
27	return c % n
28}
29
30func (mr *mockRand) uint32n(n uint32) uint32 {
31	c := mr.values[mr.counter]
32	mr.counter++
33	return uint32(c) % n
34}
35
36func (mr *mockRand) exp2() int {
37	c := mr.values[mr.counter]
38	mr.counter++
39	return c
40}
41
42func (mr *mockRand) bool() bool {
43	b := mr.b
44	mr.b = !mr.b
45	return b
46}
47
48func (mr *mockRand) save(*uint64, *uint64) {
49	panic("unimplemented")
50}
51
52func (mr *mockRand) restore(uint64, uint64) {
53	panic("unimplemented")
54}
55
56func TestByteSliceMutators(t *testing.T) {
57	for _, tc := range []struct {
58		name     string
59		mutator  func(*mutator, []byte) []byte
60		randVals []int
61		input    []byte
62		expected []byte
63	}{
64		{
65			name:     "byteSliceRemoveBytes",
66			mutator:  byteSliceRemoveBytes,
67			input:    []byte{1, 2, 3, 4},
68			expected: []byte{4},
69		},
70		{
71			name:     "byteSliceInsertRandomBytes",
72			mutator:  byteSliceInsertRandomBytes,
73			input:    make([]byte, 4, 8),
74			expected: []byte{3, 4, 5, 0, 0, 0, 0},
75		},
76		{
77			name:     "byteSliceDuplicateBytes",
78			mutator:  byteSliceDuplicateBytes,
79			input:    append(make([]byte, 0, 13), []byte{1, 2, 3, 4}...),
80			expected: []byte{1, 1, 2, 3, 4, 2, 3, 4},
81		},
82		{
83			name:     "byteSliceOverwriteBytes",
84			mutator:  byteSliceOverwriteBytes,
85			input:    []byte{1, 2, 3, 4},
86			expected: []byte{1, 1, 3, 4},
87		},
88		{
89			name:     "byteSliceBitFlip",
90			mutator:  byteSliceBitFlip,
91			input:    []byte{1, 2, 3, 4},
92			expected: []byte{3, 2, 3, 4},
93		},
94		{
95			name:     "byteSliceXORByte",
96			mutator:  byteSliceXORByte,
97			input:    []byte{1, 2, 3, 4},
98			expected: []byte{3, 2, 3, 4},
99		},
100		{
101			name:     "byteSliceSwapByte",
102			mutator:  byteSliceSwapByte,
103			input:    []byte{1, 2, 3, 4},
104			expected: []byte{2, 1, 3, 4},
105		},
106		{
107			name:     "byteSliceArithmeticUint8",
108			mutator:  byteSliceArithmeticUint8,
109			input:    []byte{1, 2, 3, 4},
110			expected: []byte{255, 2, 3, 4},
111		},
112		{
113			name:     "byteSliceArithmeticUint16",
114			mutator:  byteSliceArithmeticUint16,
115			input:    []byte{1, 2, 3, 4},
116			expected: []byte{1, 3, 3, 4},
117		},
118		{
119			name:     "byteSliceArithmeticUint32",
120			mutator:  byteSliceArithmeticUint32,
121			input:    []byte{1, 2, 3, 4},
122			expected: []byte{2, 2, 3, 4},
123		},
124		{
125			name:     "byteSliceArithmeticUint64",
126			mutator:  byteSliceArithmeticUint64,
127			input:    []byte{1, 2, 3, 4, 5, 6, 7, 8},
128			expected: []byte{2, 2, 3, 4, 5, 6, 7, 8},
129		},
130		{
131			name:     "byteSliceOverwriteInterestingUint8",
132			mutator:  byteSliceOverwriteInterestingUint8,
133			input:    []byte{1, 2, 3, 4},
134			expected: []byte{255, 2, 3, 4},
135		},
136		{
137			name:     "byteSliceOverwriteInterestingUint16",
138			mutator:  byteSliceOverwriteInterestingUint16,
139			input:    []byte{1, 2, 3, 4},
140			expected: []byte{255, 127, 3, 4},
141		},
142		{
143			name:     "byteSliceOverwriteInterestingUint32",
144			mutator:  byteSliceOverwriteInterestingUint32,
145			input:    []byte{1, 2, 3, 4},
146			expected: []byte{250, 0, 0, 250},
147		},
148		{
149			name:     "byteSliceInsertConstantBytes",
150			mutator:  byteSliceInsertConstantBytes,
151			input:    append(make([]byte, 0, 8), []byte{1, 2, 3, 4}...),
152			expected: []byte{3, 3, 3, 1, 2, 3, 4},
153		},
154		{
155			name:     "byteSliceOverwriteConstantBytes",
156			mutator:  byteSliceOverwriteConstantBytes,
157			input:    []byte{1, 2, 3, 4},
158			expected: []byte{3, 3, 3, 4},
159		},
160		{
161			name:     "byteSliceShuffleBytes",
162			mutator:  byteSliceShuffleBytes,
163			input:    []byte{1, 2, 3, 4},
164			expected: []byte{2, 3, 1, 4},
165		},
166		{
167			name:     "byteSliceSwapBytes",
168			mutator:  byteSliceSwapBytes,
169			randVals: []int{0, 2, 0, 2},
170			input:    append(make([]byte, 0, 9), []byte{1, 2, 3, 4}...),
171			expected: []byte{3, 2, 1, 4},
172		},
173	} {
174		t.Run(tc.name, func(t *testing.T) {
175			r := &mockRand{values: []int{0, 1, 2, 3, 4, 5}}
176			if tc.randVals != nil {
177				r.values = tc.randVals
178			}
179			m := &mutator{r: r}
180			b := tc.mutator(m, tc.input)
181			if !bytes.Equal(b, tc.expected) {
182				t.Errorf("got %x, want %x", b, tc.expected)
183			}
184		})
185	}
186}
187