Source file
src/internal/fuzz/minimize_test.go
1
2
3
4
5
6
7 package fuzz
8
9 import (
10 "bytes"
11 "context"
12 "errors"
13 "fmt"
14 "reflect"
15 "testing"
16 "time"
17 "unicode"
18 "unicode/utf8"
19 )
20
21 func TestMinimizeInput(t *testing.T) {
22 type testcase struct {
23 name string
24 fn func(CorpusEntry) error
25 input []any
26 expected []any
27 }
28 cases := []testcase{
29 {
30 name: "ones_byte",
31 fn: func(e CorpusEntry) error {
32 b := e.Values[0].([]byte)
33 ones := 0
34 for _, v := range b {
35 if v == 1 {
36 ones++
37 }
38 }
39 if ones == 3 {
40 return fmt.Errorf("bad %v", e.Values[0])
41 }
42 return nil
43 },
44 input: []any{[]byte{0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
45 expected: []any{[]byte{1, 1, 1}},
46 },
47 {
48 name: "single_bytes",
49 fn: func(e CorpusEntry) error {
50 b := e.Values[0].([]byte)
51 if len(b) < 2 {
52 return nil
53 }
54 if len(b) == 2 && b[0] == 1 && b[1] == 2 {
55 return nil
56 }
57 return fmt.Errorf("bad %v", e.Values[0])
58 },
59 input: []any{[]byte{1, 2, 3, 4, 5}},
60 expected: []any{[]byte("00")},
61 },
62 {
63 name: "set_of_bytes",
64 fn: func(e CorpusEntry) error {
65 b := e.Values[0].([]byte)
66 if len(b) < 3 {
67 return nil
68 }
69 if bytes.Equal(b, []byte{0, 1, 2, 3, 4, 5}) || bytes.Equal(b, []byte{0, 4, 5}) {
70 return fmt.Errorf("bad %v", e.Values[0])
71 }
72 return nil
73 },
74 input: []any{[]byte{0, 1, 2, 3, 4, 5}},
75 expected: []any{[]byte{0, 4, 5}},
76 },
77 {
78 name: "non_ascii_bytes",
79 fn: func(e CorpusEntry) error {
80 b := e.Values[0].([]byte)
81 if len(b) == 3 {
82 return fmt.Errorf("bad %v", e.Values[0])
83 }
84 return nil
85 },
86 input: []any{[]byte("ท")},
87 expected: []any{[]byte("000")},
88 },
89 {
90 name: "ones_string",
91 fn: func(e CorpusEntry) error {
92 b := e.Values[0].(string)
93 ones := 0
94 for _, v := range b {
95 if v == '1' {
96 ones++
97 }
98 }
99 if ones == 3 {
100 return fmt.Errorf("bad %v", e.Values[0])
101 }
102 return nil
103 },
104 input: []any{"001010001000000000000000000"},
105 expected: []any{"111"},
106 },
107 {
108 name: "string_length",
109 fn: func(e CorpusEntry) error {
110 b := e.Values[0].(string)
111 if len(b) == 5 {
112 return fmt.Errorf("bad %v", e.Values[0])
113 }
114 return nil
115 },
116 input: []any{"zzzzz"},
117 expected: []any{"00000"},
118 },
119 {
120 name: "string_with_letter",
121 fn: func(e CorpusEntry) error {
122 b := e.Values[0].(string)
123 r, _ := utf8.DecodeRune([]byte(b))
124 if unicode.IsLetter(r) {
125 return fmt.Errorf("bad %v", e.Values[0])
126 }
127 return nil
128 },
129 input: []any{"ZZZZZ"},
130 expected: []any{"A"},
131 },
132 }
133
134 for _, tc := range cases {
135 tc := tc
136 t.Run(tc.name, func(t *testing.T) {
137 t.Parallel()
138 ws := &workerServer{
139 fuzzFn: func(e CorpusEntry) (time.Duration, error) {
140 return time.Second, tc.fn(e)
141 },
142 }
143 mem := &sharedMem{region: make([]byte, 100)}
144 vals := tc.input
145 success, err := ws.minimizeInput(context.Background(), vals, mem, minimizeArgs{})
146 if !success {
147 t.Errorf("minimizeInput did not succeed")
148 }
149 if err == nil {
150 t.Fatal("minimizeInput didn't provide an error")
151 }
152 if expected := fmt.Sprintf("bad %v", tc.expected[0]); err.Error() != expected {
153 t.Errorf("unexpected error: got %q, want %q", err, expected)
154 }
155 if !reflect.DeepEqual(vals, tc.expected) {
156 t.Errorf("unexpected results: got %v, want %v", vals, tc.expected)
157 }
158 })
159 }
160 }
161
162
163
164
165 func TestMinimizeFlaky(t *testing.T) {
166 ws := &workerServer{fuzzFn: func(e CorpusEntry) (time.Duration, error) {
167 return time.Second, errors.New("ohno")
168 }}
169 mem := &sharedMem{region: make([]byte, 100)}
170 vals := []any{[]byte(nil)}
171 args := minimizeArgs{KeepCoverage: make([]byte, len(coverageSnapshot))}
172 success, err := ws.minimizeInput(context.Background(), vals, mem, args)
173 if success {
174 t.Error("unexpected success")
175 }
176 if err != nil {
177 t.Errorf("unexpected error: %v", err)
178 }
179 if count := mem.header().count; count != 1 {
180 t.Errorf("count: got %d, want 1", count)
181 }
182 }
183
View as plain text