1
2
3
4
5 package cgroup_test
6
7 import (
8 "internal/runtime/cgroup"
9 "io"
10 "strings"
11 "testing"
12 )
13
14 func TestLineReader(t *testing.T) {
15 type nextLine struct {
16 line string
17 incomplete bool
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 }
25
26 const scratchSize = 8
27
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 },
43 },
44 {
45 name: "single-incomplete",
46 contents: "1234",
47 want: []nextLine{
48 incomplete("1234"),
49 },
50 },
51 {
52 name: "single-exact",
53 contents: "1234567\n",
54 want: []nextLine{
55 complete("1234567"),
56 },
57 },
58 {
59 name: "single-exact-incomplete",
60 contents: "12345678",
61 want: []nextLine{
62 incomplete("12345678"),
63 },
64 },
65 {
66 name: "multi",
67 contents: `1234
68 5678
69 `,
70 want: []nextLine{
71 complete("1234"),
72 complete("5678"),
73 },
74 },
75 {
76 name: "multi-short",
77 contents: `12
78 34
79 56
80 78
81 `,
82 want: []nextLine{
83 complete("12"),
84 complete("34"),
85 complete("56"),
86 complete("78"),
87 },
88 },
89 {
90 name: "multi-notrailingnewline",
91 contents: `1234
92 5678`,
93 want: []nextLine{
94 complete("1234"),
95 incomplete("5678"),
96 },
97 },
98 {
99 name: "middle-too-long",
100 contents: `1234
101 1234567890
102 5678
103 `,
104 want: []nextLine{
105 complete("1234"),
106 incomplete("12345678"),
107 complete("5678"),
108 },
109 },
110 {
111
112 name: "middle-way-too-long",
113 contents: `1234
114 12345678900000000000000000000000000000000000000000000000000
115 5678
116 `,
117 want: []nextLine{
118 complete("1234"),
119 incomplete("12345678"),
120 complete("5678"),
121 },
122 },
123 }
124
125 for _, tc := range tests {
126 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
137 var scratch [scratchSize]byte
138 l := cgroup.NewLineReader(0, scratch[:], read)
139
140 var got []nextLine
141 for {
142 err := l.Next()
143 if err == cgroup.ErrEOF {
144 break
145 } else if err == cgroup.ErrIncompleteLine {
146 got = append(got, incomplete(string(l.Line())))
147 } else if err != nil {
148 t.Fatalf("next got err %v", err)
149 } else {
150 got = append(got, complete(string(l.Line())))
151 }
152 }
153
154 if len(got) != len(tc.want) {
155 t.Logf("got lines %+v", got)
156 t.Logf("want lines %+v", tc.want)
157 t.Fatalf("lineReader got %d lines, want %d", len(got), len(tc.want))
158 }
159
160 for i := range got {
161 if got[i].line != tc.want[i].line {
162 t.Errorf("line %d got %q want %q", i, got[i].line, tc.want[i].line)
163 }
164 if got[i].incomplete != tc.want[i].incomplete {
165 t.Errorf("line %d got incomplete %v want %v", i, got[i].incomplete, tc.want[i].incomplete)
166 }
167 }
168 })
169 }
170 }
171
View as plain text