]> Cypherpunks repositories - gostls13.git/commitdiff
internal/runtime/cgroup: lineReader fuzz test
author胡玮文 <huweiwen.hww@alibaba-inc.com>
Sun, 23 Nov 2025 18:29:24 +0000 (02:29 +0800)
committerGopher Robot <gobot@golang.org>
Mon, 1 Dec 2025 20:31:06 +0000 (12:31 -0800)
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 <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
src/internal/runtime/cgroup/line_reader_test.go

index ceef1b5b4cae46639ae6a18e6c878b8853bb4578..6095dd048192fe17402c0b01ffe8bb701bc58344 100644 (file)
@@ -11,131 +11,134 @@ import (
        "testing"
 )
 
-func TestLineReader(t *testing.T) {
-       type nextLine struct {
-               line       string
-               incomplete bool // next call before this line should return incomplete
-       }
-       complete := func(s string) nextLine {
-               return nextLine{line: s}
-       }
-       incomplete := func(s string) nextLine {
-               return nextLine{line: s, incomplete: true}
-       }
+type nextLine struct {
+       line       string
+       incomplete bool // next call before this line should return incomplete
+}
 
-       const scratchSize = 8
+func complete(s string) nextLine {
+       return nextLine{line: s}
+}
+func incomplete(s string) nextLine {
+       return nextLine{line: s, incomplete: true}
+}
 
-       tests := []struct {
-               name     string
-               contents string
-               want     []nextLine
-       }{
-               {
-                       name:     "empty",
-                       contents: "",
-               },
-               {
-                       name:     "single",
-                       contents: "1234\n",
-                       want: []nextLine{
-                               complete("1234"),
-                       },
+const scratchSize = 8
+
+var readerTests = []struct {
+       name     string
+       contents string
+       want     []nextLine
+}{
+       {
+               name:     "empty",
+               contents: "",
+       },
+       {
+               name:     "single",
+               contents: "1234\n",
+               want: []nextLine{
+                       complete("1234"),
                },
-               {
-                       name:     "single-incomplete",
-                       contents: "1234",
-                       want: []nextLine{
-                               incomplete("1234"),
-                       },
+       },
+       {
+               name:     "single-incomplete",
+               contents: "1234",
+               want: []nextLine{
+                       incomplete("1234"),
                },
-               {
-                       name:     "single-exact",
-                       contents: "1234567\n",
-                       want: []nextLine{
-                               complete("1234567"),
-                       },
+       },
+       {
+               name:     "single-exact",
+               contents: "1234567\n",
+               want: []nextLine{
+                       complete("1234567"),
                },
-               {
-                       name:     "single-exact-incomplete",
-                       contents: "12345678",
-                       want: []nextLine{
-                               incomplete("12345678"),
-                       },
+       },
+       {
+               name:     "single-exact-incomplete",
+               contents: "12345678",
+               want: []nextLine{
+                       incomplete("12345678"),
                },
-               {
-                       name: "multi",
-                       contents: `1234
+       },
+       {
+               name: "multi",
+               contents: `1234
 5678
 `,
-                       want: []nextLine{
-                               complete("1234"),
-                               complete("5678"),
-                       },
+               want: []nextLine{
+                       complete("1234"),
+                       complete("5678"),
                },
-               {
-                       name: "multi-short",
-                       contents: `12
+       },
+       {
+               name: "multi-short",
+               contents: `12
 34
 56
 78
 `,
-                       want: []nextLine{
-                               complete("12"),
-                               complete("34"),
-                               complete("56"),
-                               complete("78"),
-                       },
+               want: []nextLine{
+                       complete("12"),
+                       complete("34"),
+                       complete("56"),
+                       complete("78"),
                },
-               {
-                       name: "multi-notrailingnewline",
-                       contents: `1234
+       },
+       {
+               name: "multi-notrailingnewline",
+               contents: `1234
 5678`,
-                       want: []nextLine{
-                               complete("1234"),
-                               incomplete("5678"),
-                       },
+               want: []nextLine{
+                       complete("1234"),
+                       incomplete("5678"),
                },
-               {
-                       name: "middle-too-long",
-                       contents: `1234
+       },
+       {
+               name: "middle-too-long",
+               contents: `1234
 1234567890
 5678
 `,
-                       want: []nextLine{
-                               complete("1234"),
-                               incomplete("12345678"),
-                               complete("5678"),
-                       },
+               want: []nextLine{
+                       complete("1234"),
+                       incomplete("12345678"),
+                       complete("5678"),
                },
-               {
-                       // Multiple reads required to find newline.
-                       name: "middle-way-too-long",
-                       contents: `1234
+       },
+       {
+               // Multiple reads required to find newline.
+               name: "middle-way-too-long",
+               contents: `1234
 12345678900000000000000000000000000000000000000000000000000
 5678
 `,
-                       want: []nextLine{
-                               complete("1234"),
-                               incomplete("12345678"),
-                               complete("5678"),
-                       },
+               want: []nextLine{
+                       complete("1234"),
+                       incomplete("12345678"),
+                       complete("5678"),
                },
+       },
+}
+
+func readString(contents string) func(fd int, b []byte) (int, uintptr) {
+       r := strings.NewReader(contents)
+       return func(fd int, b []byte) (int, uintptr) {
+               n, err := r.Read(b)
+               if err != nil && err != io.EOF {
+                       const dummyErrno = 42
+                       return n, dummyErrno
+               }
+               return n, 0
        }
+}
 
-       for _, tc := range tests {
+func TestLineReader(t *testing.T) {
+       for _, tc := range readerTests {
                t.Run(tc.name, func(t *testing.T) {
-                       r := strings.NewReader(tc.contents)
-                       read := func(fd int, b []byte) (int, uintptr) {
-                               n, err := r.Read(b)
-                               if err != nil && err != io.EOF {
-                                       const dummyErrno = 42
-                                       return n, dummyErrno
-                               }
-                               return n, 0
-                       }
-
                        var scratch [scratchSize]byte
-                       l := cgroup.NewLineReader(0, scratch[:], read)
+                       l := cgroup.NewLineReader(0, scratch[:], readString(tc.contents))
 
                        var got []nextLine
                        for {
@@ -168,3 +171,39 @@ func TestLineReader(t *testing.T) {
                })
        }
 }
+
+func FuzzLineReader(f *testing.F) {
+       for _, tc := range readerTests {
+               f.Add(tc.contents)
+       }
+       f.Fuzz(func(t *testing.T, input string) {
+               scratch := make([]byte, scratchSize)
+               reader := cgroup.NewLineReader(0, scratch, readString(input))
+               for expected := range strings.Lines(input) {
+                       err := reader.Next()
+                       line := reader.Line()
+
+                       var expectedErr error
+                       if len(expected) > scratchSize {
+                               expected = expected[:scratchSize]
+                               expectedErr = cgroup.ErrIncompleteLine
+                       } else if expected[len(expected)-1] == '\n' {
+                               expected = expected[:len(expected)-1]
+                       } else {
+                               expectedErr = cgroup.ErrIncompleteLine
+                       }
+
+                       if err != expectedErr {
+                               t.Fatalf("got err %v, want %v", err, expectedErr)
+                       }
+
+                       if string(line) != expected {
+                               t.Fatalf("got %q, want %q", string(line), expected)
+                       }
+               }
+               err := reader.Next()
+               if err != cgroup.ErrEOF {
+                       t.Fatalf("got %v, want EOF", err)
+               }
+       })
+}