Source file
src/internal/fuzz/mutators_byteslice_test.go
1
2
3
4
5 package fuzz
6
7 import (
8 "bytes"
9 "fmt"
10 "testing"
11 )
12
13 type mockRand struct {
14 values []int
15 counter int
16 b bool
17 }
18
19 func (mr *mockRand) uint32() uint32 {
20 c := mr.values[mr.counter]
21 mr.counter++
22 return uint32(c)
23 }
24
25 func (mr *mockRand) intn(n int) int {
26 c := mr.values[mr.counter]
27 mr.counter++
28 return c % n
29 }
30
31 func (mr *mockRand) uint32n(n uint32) uint32 {
32 c := mr.values[mr.counter]
33 mr.counter++
34 return uint32(c) % n
35 }
36
37 func (mr *mockRand) bool() bool {
38 b := mr.b
39 mr.b = !mr.b
40 return b
41 }
42
43 func (mr *mockRand) save(*uint64, *uint64) {
44 panic("unimplemented")
45 }
46
47 func (mr *mockRand) restore(uint64, uint64) {
48 panic("unimplemented")
49 }
50
51 func TestByteSliceMutators(t *testing.T) {
52 for _, tc := range []struct {
53 name string
54 mutator func(*mutator, []byte) []byte
55 randVals []int
56 input []byte
57 expected []byte
58 }{
59 {
60 name: "byteSliceRemoveBytes",
61 mutator: byteSliceRemoveBytes,
62 input: []byte{1, 2, 3, 4},
63 expected: []byte{4},
64 },
65 {
66 name: "byteSliceInsertRandomBytes",
67 mutator: byteSliceInsertRandomBytes,
68 input: make([]byte, 4, 8),
69 expected: []byte{3, 4, 5, 0, 0, 0, 0},
70 },
71 {
72 name: "byteSliceDuplicateBytes",
73 mutator: byteSliceDuplicateBytes,
74 input: append(make([]byte, 0, 13), []byte{1, 2, 3, 4}...),
75 expected: []byte{1, 1, 2, 3, 4, 2, 3, 4},
76 },
77 {
78 name: "byteSliceOverwriteBytes",
79 mutator: byteSliceOverwriteBytes,
80 input: []byte{1, 2, 3, 4},
81 expected: []byte{1, 1, 3, 4},
82 },
83 {
84 name: "byteSliceBitFlip",
85 mutator: byteSliceBitFlip,
86 input: []byte{1, 2, 3, 4},
87 expected: []byte{3, 2, 3, 4},
88 },
89 {
90 name: "byteSliceXORByte",
91 mutator: byteSliceXORByte,
92 input: []byte{1, 2, 3, 4},
93 expected: []byte{3, 2, 3, 4},
94 },
95 {
96 name: "byteSliceSwapByte",
97 mutator: byteSliceSwapByte,
98 input: []byte{1, 2, 3, 4},
99 expected: []byte{2, 1, 3, 4},
100 },
101 {
102 name: "byteSliceArithmeticUint8",
103 mutator: byteSliceArithmeticUint8,
104 input: []byte{1, 2, 3, 4},
105 expected: []byte{255, 2, 3, 4},
106 },
107 {
108 name: "byteSliceArithmeticUint16",
109 mutator: byteSliceArithmeticUint16,
110 input: []byte{1, 2, 3, 4},
111 expected: []byte{1, 3, 3, 4},
112 },
113 {
114 name: "byteSliceArithmeticUint32",
115 mutator: byteSliceArithmeticUint32,
116 input: []byte{1, 2, 3, 4},
117 expected: []byte{2, 2, 3, 4},
118 },
119 {
120 name: "byteSliceArithmeticUint64",
121 mutator: byteSliceArithmeticUint64,
122 input: []byte{1, 2, 3, 4, 5, 6, 7, 8},
123 expected: []byte{2, 2, 3, 4, 5, 6, 7, 8},
124 },
125 {
126 name: "byteSliceOverwriteInterestingUint8",
127 mutator: byteSliceOverwriteInterestingUint8,
128 input: []byte{1, 2, 3, 4},
129 expected: []byte{255, 2, 3, 4},
130 },
131 {
132 name: "byteSliceOverwriteInterestingUint16",
133 mutator: byteSliceOverwriteInterestingUint16,
134 input: []byte{1, 2, 3, 4},
135 expected: []byte{255, 127, 3, 4},
136 },
137 {
138 name: "byteSliceOverwriteInterestingUint32",
139 mutator: byteSliceOverwriteInterestingUint32,
140 input: []byte{1, 2, 3, 4},
141 expected: []byte{250, 0, 0, 250},
142 },
143 {
144 name: "byteSliceInsertConstantBytes",
145 mutator: byteSliceInsertConstantBytes,
146 input: append(make([]byte, 0, 8), []byte{1, 2, 3, 4}...),
147 expected: []byte{3, 3, 3, 1, 2, 3, 4},
148 },
149 {
150 name: "byteSliceOverwriteConstantBytes",
151 mutator: byteSliceOverwriteConstantBytes,
152 input: []byte{1, 2, 3, 4},
153 expected: []byte{3, 3, 3, 4},
154 },
155 {
156 name: "byteSliceShuffleBytes",
157 mutator: byteSliceShuffleBytes,
158 input: []byte{1, 2, 3, 4},
159 expected: []byte{2, 3, 1, 4},
160 },
161 {
162 name: "byteSliceSwapBytes",
163 mutator: byteSliceSwapBytes,
164 randVals: []int{0, 2, 0, 2},
165 input: append(make([]byte, 0, 9), []byte{1, 2, 3, 4}...),
166 expected: []byte{3, 2, 1, 4},
167 },
168 } {
169 t.Run(tc.name, func(t *testing.T) {
170 r := &mockRand{values: []int{0, 1, 2, 3, 4, 5}}
171 if tc.randVals != nil {
172 r.values = tc.randVals
173 }
174 m := &mutator{r: r}
175 b := tc.mutator(m, tc.input)
176 if !bytes.Equal(b, tc.expected) {
177 t.Errorf("got %x, want %x", b, tc.expected)
178 }
179 })
180 }
181 }
182
183 func BenchmarkByteSliceMutators(b *testing.B) {
184 tests := [...]struct {
185 name string
186 mutator func(*mutator, []byte) []byte
187 }{
188 {"RemoveBytes", byteSliceRemoveBytes},
189 {"InsertRandomBytes", byteSliceInsertRandomBytes},
190 {"DuplicateBytes", byteSliceDuplicateBytes},
191 {"OverwriteBytes", byteSliceOverwriteBytes},
192 {"BitFlip", byteSliceBitFlip},
193 {"XORByte", byteSliceXORByte},
194 {"SwapByte", byteSliceSwapByte},
195 {"ArithmeticUint8", byteSliceArithmeticUint8},
196 {"ArithmeticUint16", byteSliceArithmeticUint16},
197 {"ArithmeticUint32", byteSliceArithmeticUint32},
198 {"ArithmeticUint64", byteSliceArithmeticUint64},
199 {"OverwriteInterestingUint8", byteSliceOverwriteInterestingUint8},
200 {"OverwriteInterestingUint16", byteSliceOverwriteInterestingUint16},
201 {"OverwriteInterestingUint32", byteSliceOverwriteInterestingUint32},
202 {"InsertConstantBytes", byteSliceInsertConstantBytes},
203 {"OverwriteConstantBytes", byteSliceOverwriteConstantBytes},
204 {"ShuffleBytes", byteSliceShuffleBytes},
205 {"SwapBytes", byteSliceSwapBytes},
206 }
207
208 for _, tc := range tests {
209 b.Run(tc.name, func(b *testing.B) {
210 for size := 64; size <= 1024; size *= 2 {
211 b.Run(fmt.Sprintf("%d", size), func(b *testing.B) {
212 m := &mutator{r: newPcgRand()}
213 input := make([]byte, size)
214 for i := 0; i < b.N; i++ {
215 tc.mutator(m, input)
216 }
217 })
218 }
219 })
220 }
221 }
222
View as plain text