Skip to content

Commit 6785154

Browse files
huww98gopherbot
authored andcommitted
internal/runtime/cgroup: lineReader fuzz test
The original unit test is converted to a fuzz test, to be more confident on future refactors. All sub-tests are converted to seed corpus. Change-Id: Id0c167ed47729a00ea0614d17746ddcc284697d3 Reviewed-on: https://go-review.googlesource.com/c/go/+/723581 Auto-Submit: Michael Pratt <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: Michael Pratt <[email protected]>
1 parent ac3e0ae commit 6785154

File tree

1 file changed

+136
-97
lines changed

1 file changed

+136
-97
lines changed

src/internal/runtime/cgroup/line_reader_test.go

Lines changed: 136 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -11,131 +11,134 @@ import (
1111
"testing"
1212
)
1313

14-
func TestLineReader(t *testing.T) {
15-
type nextLine struct {
16-
line string
17-
incomplete bool // next call before this line should return incomplete
18-
}
19-
complete := func(s string) nextLine {
20-
return nextLine{line: s}
21-
}
22-
incomplete := func(s string) nextLine {
23-
return nextLine{line: s, incomplete: true}
24-
}
14+
type nextLine struct {
15+
line string
16+
incomplete bool // next call before this line should return incomplete
17+
}
2518

26-
const scratchSize = 8
19+
func complete(s string) nextLine {
20+
return nextLine{line: s}
21+
}
22+
func incomplete(s string) nextLine {
23+
return nextLine{line: s, incomplete: true}
24+
}
2725

28-
tests := []struct {
29-
name string
30-
contents string
31-
want []nextLine
32-
}{
33-
{
34-
name: "empty",
35-
contents: "",
36-
},
37-
{
38-
name: "single",
39-
contents: "1234\n",
40-
want: []nextLine{
41-
complete("1234"),
42-
},
26+
const scratchSize = 8
27+
28+
var readerTests = []struct {
29+
name string
30+
contents string
31+
want []nextLine
32+
}{
33+
{
34+
name: "empty",
35+
contents: "",
36+
},
37+
{
38+
name: "single",
39+
contents: "1234\n",
40+
want: []nextLine{
41+
complete("1234"),
4342
},
44-
{
45-
name: "single-incomplete",
46-
contents: "1234",
47-
want: []nextLine{
48-
incomplete("1234"),
49-
},
43+
},
44+
{
45+
name: "single-incomplete",
46+
contents: "1234",
47+
want: []nextLine{
48+
incomplete("1234"),
5049
},
51-
{
52-
name: "single-exact",
53-
contents: "1234567\n",
54-
want: []nextLine{
55-
complete("1234567"),
56-
},
50+
},
51+
{
52+
name: "single-exact",
53+
contents: "1234567\n",
54+
want: []nextLine{
55+
complete("1234567"),
5756
},
58-
{
59-
name: "single-exact-incomplete",
60-
contents: "12345678",
61-
want: []nextLine{
62-
incomplete("12345678"),
63-
},
57+
},
58+
{
59+
name: "single-exact-incomplete",
60+
contents: "12345678",
61+
want: []nextLine{
62+
incomplete("12345678"),
6463
},
65-
{
66-
name: "multi",
67-
contents: `1234
64+
},
65+
{
66+
name: "multi",
67+
contents: `1234
6868
5678
6969
`,
70-
want: []nextLine{
71-
complete("1234"),
72-
complete("5678"),
73-
},
70+
want: []nextLine{
71+
complete("1234"),
72+
complete("5678"),
7473
},
75-
{
76-
name: "multi-short",
77-
contents: `12
74+
},
75+
{
76+
name: "multi-short",
77+
contents: `12
7878
34
7979
56
8080
78
8181
`,
82-
want: []nextLine{
83-
complete("12"),
84-
complete("34"),
85-
complete("56"),
86-
complete("78"),
87-
},
82+
want: []nextLine{
83+
complete("12"),
84+
complete("34"),
85+
complete("56"),
86+
complete("78"),
8887
},
89-
{
90-
name: "multi-notrailingnewline",
91-
contents: `1234
88+
},
89+
{
90+
name: "multi-notrailingnewline",
91+
contents: `1234
9292
5678`,
93-
want: []nextLine{
94-
complete("1234"),
95-
incomplete("5678"),
96-
},
93+
want: []nextLine{
94+
complete("1234"),
95+
incomplete("5678"),
9796
},
98-
{
99-
name: "middle-too-long",
100-
contents: `1234
97+
},
98+
{
99+
name: "middle-too-long",
100+
contents: `1234
101101
1234567890
102102
5678
103103
`,
104-
want: []nextLine{
105-
complete("1234"),
106-
incomplete("12345678"),
107-
complete("5678"),
108-
},
104+
want: []nextLine{
105+
complete("1234"),
106+
incomplete("12345678"),
107+
complete("5678"),
109108
},
110-
{
111-
// Multiple reads required to find newline.
112-
name: "middle-way-too-long",
113-
contents: `1234
109+
},
110+
{
111+
// Multiple reads required to find newline.
112+
name: "middle-way-too-long",
113+
contents: `1234
114114
12345678900000000000000000000000000000000000000000000000000
115115
5678
116116
`,
117-
want: []nextLine{
118-
complete("1234"),
119-
incomplete("12345678"),
120-
complete("5678"),
121-
},
117+
want: []nextLine{
118+
complete("1234"),
119+
incomplete("12345678"),
120+
complete("5678"),
122121
},
122+
},
123+
}
124+
125+
func readString(contents string) func(fd int, b []byte) (int, uintptr) {
126+
r := strings.NewReader(contents)
127+
return func(fd int, b []byte) (int, uintptr) {
128+
n, err := r.Read(b)
129+
if err != nil && err != io.EOF {
130+
const dummyErrno = 42
131+
return n, dummyErrno
132+
}
133+
return n, 0
123134
}
135+
}
124136

125-
for _, tc := range tests {
137+
func TestLineReader(t *testing.T) {
138+
for _, tc := range readerTests {
126139
t.Run(tc.name, func(t *testing.T) {
127-
r := strings.NewReader(tc.contents)
128-
read := func(fd int, b []byte) (int, uintptr) {
129-
n, err := r.Read(b)
130-
if err != nil && err != io.EOF {
131-
const dummyErrno = 42
132-
return n, dummyErrno
133-
}
134-
return n, 0
135-
}
136-
137140
var scratch [scratchSize]byte
138-
l := cgroup.NewLineReader(0, scratch[:], read)
141+
l := cgroup.NewLineReader(0, scratch[:], readString(tc.contents))
139142

140143
var got []nextLine
141144
for {
@@ -168,3 +171,39 @@ func TestLineReader(t *testing.T) {
168171
})
169172
}
170173
}
174+
175+
func FuzzLineReader(f *testing.F) {
176+
for _, tc := range readerTests {
177+
f.Add(tc.contents)
178+
}
179+
f.Fuzz(func(t *testing.T, input string) {
180+
scratch := make([]byte, scratchSize)
181+
reader := cgroup.NewLineReader(0, scratch, readString(input))
182+
for expected := range strings.Lines(input) {
183+
err := reader.Next()
184+
line := reader.Line()
185+
186+
var expectedErr error
187+
if len(expected) > scratchSize {
188+
expected = expected[:scratchSize]
189+
expectedErr = cgroup.ErrIncompleteLine
190+
} else if expected[len(expected)-1] == '\n' {
191+
expected = expected[:len(expected)-1]
192+
} else {
193+
expectedErr = cgroup.ErrIncompleteLine
194+
}
195+
196+
if err != expectedErr {
197+
t.Fatalf("got err %v, want %v", err, expectedErr)
198+
}
199+
200+
if string(line) != expected {
201+
t.Fatalf("got %q, want %q", string(line), expected)
202+
}
203+
}
204+
err := reader.Next()
205+
if err != cgroup.ErrEOF {
206+
t.Fatalf("got %v, want EOF", err)
207+
}
208+
})
209+
}

0 commit comments

Comments
 (0)