blob: 788696788187247c23e07793e084541cddd09875 [file] [log] [blame]
Dan Willemsenbc60c3c2021-12-15 01:09:00 -08001// 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}