annotate libgo/go/io/pipe_test.go @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 // Copyright 2009 The Go Authors. All rights reserved.
kono
parents:
diff changeset
2 // Use of this source code is governed by a BSD-style
kono
parents:
diff changeset
3 // license that can be found in the LICENSE file.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 package io_test
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 import (
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
8 "bytes"
111
kono
parents:
diff changeset
9 "fmt"
kono
parents:
diff changeset
10 . "io"
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
11 "sort"
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
12 "strings"
111
kono
parents:
diff changeset
13 "testing"
kono
parents:
diff changeset
14 "time"
kono
parents:
diff changeset
15 )
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 func checkWrite(t *testing.T, w Writer, data []byte, c chan int) {
kono
parents:
diff changeset
18 n, err := w.Write(data)
kono
parents:
diff changeset
19 if err != nil {
kono
parents:
diff changeset
20 t.Errorf("write: %v", err)
kono
parents:
diff changeset
21 }
kono
parents:
diff changeset
22 if n != len(data) {
kono
parents:
diff changeset
23 t.Errorf("short write: %d != %d", n, len(data))
kono
parents:
diff changeset
24 }
kono
parents:
diff changeset
25 c <- 0
kono
parents:
diff changeset
26 }
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 // Test a single read/write pair.
kono
parents:
diff changeset
29 func TestPipe1(t *testing.T) {
kono
parents:
diff changeset
30 c := make(chan int)
kono
parents:
diff changeset
31 r, w := Pipe()
kono
parents:
diff changeset
32 var buf = make([]byte, 64)
kono
parents:
diff changeset
33 go checkWrite(t, w, []byte("hello, world"), c)
kono
parents:
diff changeset
34 n, err := r.Read(buf)
kono
parents:
diff changeset
35 if err != nil {
kono
parents:
diff changeset
36 t.Errorf("read: %v", err)
kono
parents:
diff changeset
37 } else if n != 12 || string(buf[0:12]) != "hello, world" {
kono
parents:
diff changeset
38 t.Errorf("bad read: got %q", buf[0:n])
kono
parents:
diff changeset
39 }
kono
parents:
diff changeset
40 <-c
kono
parents:
diff changeset
41 r.Close()
kono
parents:
diff changeset
42 w.Close()
kono
parents:
diff changeset
43 }
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 func reader(t *testing.T, r Reader, c chan int) {
kono
parents:
diff changeset
46 var buf = make([]byte, 64)
kono
parents:
diff changeset
47 for {
kono
parents:
diff changeset
48 n, err := r.Read(buf)
kono
parents:
diff changeset
49 if err == EOF {
kono
parents:
diff changeset
50 c <- 0
kono
parents:
diff changeset
51 break
kono
parents:
diff changeset
52 }
kono
parents:
diff changeset
53 if err != nil {
kono
parents:
diff changeset
54 t.Errorf("read: %v", err)
kono
parents:
diff changeset
55 }
kono
parents:
diff changeset
56 c <- n
kono
parents:
diff changeset
57 }
kono
parents:
diff changeset
58 }
kono
parents:
diff changeset
59
kono
parents:
diff changeset
60 // Test a sequence of read/write pairs.
kono
parents:
diff changeset
61 func TestPipe2(t *testing.T) {
kono
parents:
diff changeset
62 c := make(chan int)
kono
parents:
diff changeset
63 r, w := Pipe()
kono
parents:
diff changeset
64 go reader(t, r, c)
kono
parents:
diff changeset
65 var buf = make([]byte, 64)
kono
parents:
diff changeset
66 for i := 0; i < 5; i++ {
kono
parents:
diff changeset
67 p := buf[0 : 5+i*10]
kono
parents:
diff changeset
68 n, err := w.Write(p)
kono
parents:
diff changeset
69 if n != len(p) {
kono
parents:
diff changeset
70 t.Errorf("wrote %d, got %d", len(p), n)
kono
parents:
diff changeset
71 }
kono
parents:
diff changeset
72 if err != nil {
kono
parents:
diff changeset
73 t.Errorf("write: %v", err)
kono
parents:
diff changeset
74 }
kono
parents:
diff changeset
75 nn := <-c
kono
parents:
diff changeset
76 if nn != n {
kono
parents:
diff changeset
77 t.Errorf("wrote %d, read got %d", n, nn)
kono
parents:
diff changeset
78 }
kono
parents:
diff changeset
79 }
kono
parents:
diff changeset
80 w.Close()
kono
parents:
diff changeset
81 nn := <-c
kono
parents:
diff changeset
82 if nn != 0 {
kono
parents:
diff changeset
83 t.Errorf("final read got %d", nn)
kono
parents:
diff changeset
84 }
kono
parents:
diff changeset
85 }
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 type pipeReturn struct {
kono
parents:
diff changeset
88 n int
kono
parents:
diff changeset
89 err error
kono
parents:
diff changeset
90 }
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 // Test a large write that requires multiple reads to satisfy.
kono
parents:
diff changeset
93 func writer(w WriteCloser, buf []byte, c chan pipeReturn) {
kono
parents:
diff changeset
94 n, err := w.Write(buf)
kono
parents:
diff changeset
95 w.Close()
kono
parents:
diff changeset
96 c <- pipeReturn{n, err}
kono
parents:
diff changeset
97 }
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 func TestPipe3(t *testing.T) {
kono
parents:
diff changeset
100 c := make(chan pipeReturn)
kono
parents:
diff changeset
101 r, w := Pipe()
kono
parents:
diff changeset
102 var wdat = make([]byte, 128)
kono
parents:
diff changeset
103 for i := 0; i < len(wdat); i++ {
kono
parents:
diff changeset
104 wdat[i] = byte(i)
kono
parents:
diff changeset
105 }
kono
parents:
diff changeset
106 go writer(w, wdat, c)
kono
parents:
diff changeset
107 var rdat = make([]byte, 1024)
kono
parents:
diff changeset
108 tot := 0
kono
parents:
diff changeset
109 for n := 1; n <= 256; n *= 2 {
kono
parents:
diff changeset
110 nn, err := r.Read(rdat[tot : tot+n])
kono
parents:
diff changeset
111 if err != nil && err != EOF {
kono
parents:
diff changeset
112 t.Fatalf("read: %v", err)
kono
parents:
diff changeset
113 }
kono
parents:
diff changeset
114
kono
parents:
diff changeset
115 // only final two reads should be short - 1 byte, then 0
kono
parents:
diff changeset
116 expect := n
kono
parents:
diff changeset
117 if n == 128 {
kono
parents:
diff changeset
118 expect = 1
kono
parents:
diff changeset
119 } else if n == 256 {
kono
parents:
diff changeset
120 expect = 0
kono
parents:
diff changeset
121 if err != EOF {
kono
parents:
diff changeset
122 t.Fatalf("read at end: %v", err)
kono
parents:
diff changeset
123 }
kono
parents:
diff changeset
124 }
kono
parents:
diff changeset
125 if nn != expect {
kono
parents:
diff changeset
126 t.Fatalf("read %d, expected %d, got %d", n, expect, nn)
kono
parents:
diff changeset
127 }
kono
parents:
diff changeset
128 tot += nn
kono
parents:
diff changeset
129 }
kono
parents:
diff changeset
130 pr := <-c
kono
parents:
diff changeset
131 if pr.n != 128 || pr.err != nil {
kono
parents:
diff changeset
132 t.Fatalf("write 128: %d, %v", pr.n, pr.err)
kono
parents:
diff changeset
133 }
kono
parents:
diff changeset
134 if tot != 128 {
kono
parents:
diff changeset
135 t.Fatalf("total read %d != 128", tot)
kono
parents:
diff changeset
136 }
kono
parents:
diff changeset
137 for i := 0; i < 128; i++ {
kono
parents:
diff changeset
138 if rdat[i] != byte(i) {
kono
parents:
diff changeset
139 t.Fatalf("rdat[%d] = %d", i, rdat[i])
kono
parents:
diff changeset
140 }
kono
parents:
diff changeset
141 }
kono
parents:
diff changeset
142 }
kono
parents:
diff changeset
143
kono
parents:
diff changeset
144 // Test read after/before writer close.
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146 type closer interface {
kono
parents:
diff changeset
147 CloseWithError(error) error
kono
parents:
diff changeset
148 Close() error
kono
parents:
diff changeset
149 }
kono
parents:
diff changeset
150
kono
parents:
diff changeset
151 type pipeTest struct {
kono
parents:
diff changeset
152 async bool
kono
parents:
diff changeset
153 err error
kono
parents:
diff changeset
154 closeWithError bool
kono
parents:
diff changeset
155 }
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 func (p pipeTest) String() string {
kono
parents:
diff changeset
158 return fmt.Sprintf("async=%v err=%v closeWithError=%v", p.async, p.err, p.closeWithError)
kono
parents:
diff changeset
159 }
kono
parents:
diff changeset
160
kono
parents:
diff changeset
161 var pipeTests = []pipeTest{
kono
parents:
diff changeset
162 {true, nil, false},
kono
parents:
diff changeset
163 {true, nil, true},
kono
parents:
diff changeset
164 {true, ErrShortWrite, true},
kono
parents:
diff changeset
165 {false, nil, false},
kono
parents:
diff changeset
166 {false, nil, true},
kono
parents:
diff changeset
167 {false, ErrShortWrite, true},
kono
parents:
diff changeset
168 }
kono
parents:
diff changeset
169
kono
parents:
diff changeset
170 func delayClose(t *testing.T, cl closer, ch chan int, tt pipeTest) {
kono
parents:
diff changeset
171 time.Sleep(1 * time.Millisecond)
kono
parents:
diff changeset
172 var err error
kono
parents:
diff changeset
173 if tt.closeWithError {
kono
parents:
diff changeset
174 err = cl.CloseWithError(tt.err)
kono
parents:
diff changeset
175 } else {
kono
parents:
diff changeset
176 err = cl.Close()
kono
parents:
diff changeset
177 }
kono
parents:
diff changeset
178 if err != nil {
kono
parents:
diff changeset
179 t.Errorf("delayClose: %v", err)
kono
parents:
diff changeset
180 }
kono
parents:
diff changeset
181 ch <- 0
kono
parents:
diff changeset
182 }
kono
parents:
diff changeset
183
kono
parents:
diff changeset
184 func TestPipeReadClose(t *testing.T) {
kono
parents:
diff changeset
185 for _, tt := range pipeTests {
kono
parents:
diff changeset
186 c := make(chan int, 1)
kono
parents:
diff changeset
187 r, w := Pipe()
kono
parents:
diff changeset
188 if tt.async {
kono
parents:
diff changeset
189 go delayClose(t, w, c, tt)
kono
parents:
diff changeset
190 } else {
kono
parents:
diff changeset
191 delayClose(t, w, c, tt)
kono
parents:
diff changeset
192 }
kono
parents:
diff changeset
193 var buf = make([]byte, 64)
kono
parents:
diff changeset
194 n, err := r.Read(buf)
kono
parents:
diff changeset
195 <-c
kono
parents:
diff changeset
196 want := tt.err
kono
parents:
diff changeset
197 if want == nil {
kono
parents:
diff changeset
198 want = EOF
kono
parents:
diff changeset
199 }
kono
parents:
diff changeset
200 if err != want {
kono
parents:
diff changeset
201 t.Errorf("read from closed pipe: %v want %v", err, want)
kono
parents:
diff changeset
202 }
kono
parents:
diff changeset
203 if n != 0 {
kono
parents:
diff changeset
204 t.Errorf("read on closed pipe returned %d", n)
kono
parents:
diff changeset
205 }
kono
parents:
diff changeset
206 if err = r.Close(); err != nil {
kono
parents:
diff changeset
207 t.Errorf("r.Close: %v", err)
kono
parents:
diff changeset
208 }
kono
parents:
diff changeset
209 }
kono
parents:
diff changeset
210 }
kono
parents:
diff changeset
211
kono
parents:
diff changeset
212 // Test close on Read side during Read.
kono
parents:
diff changeset
213 func TestPipeReadClose2(t *testing.T) {
kono
parents:
diff changeset
214 c := make(chan int, 1)
kono
parents:
diff changeset
215 r, _ := Pipe()
kono
parents:
diff changeset
216 go delayClose(t, r, c, pipeTest{})
kono
parents:
diff changeset
217 n, err := r.Read(make([]byte, 64))
kono
parents:
diff changeset
218 <-c
kono
parents:
diff changeset
219 if n != 0 || err != ErrClosedPipe {
kono
parents:
diff changeset
220 t.Errorf("read from closed pipe: %v, %v want %v, %v", n, err, 0, ErrClosedPipe)
kono
parents:
diff changeset
221 }
kono
parents:
diff changeset
222 }
kono
parents:
diff changeset
223
kono
parents:
diff changeset
224 // Test write after/before reader close.
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 func TestPipeWriteClose(t *testing.T) {
kono
parents:
diff changeset
227 for _, tt := range pipeTests {
kono
parents:
diff changeset
228 c := make(chan int, 1)
kono
parents:
diff changeset
229 r, w := Pipe()
kono
parents:
diff changeset
230 if tt.async {
kono
parents:
diff changeset
231 go delayClose(t, r, c, tt)
kono
parents:
diff changeset
232 } else {
kono
parents:
diff changeset
233 delayClose(t, r, c, tt)
kono
parents:
diff changeset
234 }
kono
parents:
diff changeset
235 n, err := WriteString(w, "hello, world")
kono
parents:
diff changeset
236 <-c
kono
parents:
diff changeset
237 expect := tt.err
kono
parents:
diff changeset
238 if expect == nil {
kono
parents:
diff changeset
239 expect = ErrClosedPipe
kono
parents:
diff changeset
240 }
kono
parents:
diff changeset
241 if err != expect {
kono
parents:
diff changeset
242 t.Errorf("write on closed pipe: %v want %v", err, expect)
kono
parents:
diff changeset
243 }
kono
parents:
diff changeset
244 if n != 0 {
kono
parents:
diff changeset
245 t.Errorf("write on closed pipe returned %d", n)
kono
parents:
diff changeset
246 }
kono
parents:
diff changeset
247 if err = w.Close(); err != nil {
kono
parents:
diff changeset
248 t.Errorf("w.Close: %v", err)
kono
parents:
diff changeset
249 }
kono
parents:
diff changeset
250 }
kono
parents:
diff changeset
251 }
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253 // Test close on Write side during Write.
kono
parents:
diff changeset
254 func TestPipeWriteClose2(t *testing.T) {
kono
parents:
diff changeset
255 c := make(chan int, 1)
kono
parents:
diff changeset
256 _, w := Pipe()
kono
parents:
diff changeset
257 go delayClose(t, w, c, pipeTest{})
kono
parents:
diff changeset
258 n, err := w.Write(make([]byte, 64))
kono
parents:
diff changeset
259 <-c
kono
parents:
diff changeset
260 if n != 0 || err != ErrClosedPipe {
kono
parents:
diff changeset
261 t.Errorf("write to closed pipe: %v, %v want %v, %v", n, err, 0, ErrClosedPipe)
kono
parents:
diff changeset
262 }
kono
parents:
diff changeset
263 }
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 func TestWriteEmpty(t *testing.T) {
kono
parents:
diff changeset
266 r, w := Pipe()
kono
parents:
diff changeset
267 go func() {
kono
parents:
diff changeset
268 w.Write([]byte{})
kono
parents:
diff changeset
269 w.Close()
kono
parents:
diff changeset
270 }()
kono
parents:
diff changeset
271 var b [2]byte
kono
parents:
diff changeset
272 ReadFull(r, b[0:2])
kono
parents:
diff changeset
273 r.Close()
kono
parents:
diff changeset
274 }
kono
parents:
diff changeset
275
kono
parents:
diff changeset
276 func TestWriteNil(t *testing.T) {
kono
parents:
diff changeset
277 r, w := Pipe()
kono
parents:
diff changeset
278 go func() {
kono
parents:
diff changeset
279 w.Write(nil)
kono
parents:
diff changeset
280 w.Close()
kono
parents:
diff changeset
281 }()
kono
parents:
diff changeset
282 var b [2]byte
kono
parents:
diff changeset
283 ReadFull(r, b[0:2])
kono
parents:
diff changeset
284 r.Close()
kono
parents:
diff changeset
285 }
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 func TestWriteAfterWriterClose(t *testing.T) {
kono
parents:
diff changeset
288 r, w := Pipe()
kono
parents:
diff changeset
289
kono
parents:
diff changeset
290 done := make(chan bool)
kono
parents:
diff changeset
291 var writeErr error
kono
parents:
diff changeset
292 go func() {
kono
parents:
diff changeset
293 _, err := w.Write([]byte("hello"))
kono
parents:
diff changeset
294 if err != nil {
kono
parents:
diff changeset
295 t.Errorf("got error: %q; expected none", err)
kono
parents:
diff changeset
296 }
kono
parents:
diff changeset
297 w.Close()
kono
parents:
diff changeset
298 _, writeErr = w.Write([]byte("world"))
kono
parents:
diff changeset
299 done <- true
kono
parents:
diff changeset
300 }()
kono
parents:
diff changeset
301
kono
parents:
diff changeset
302 buf := make([]byte, 100)
kono
parents:
diff changeset
303 var result string
kono
parents:
diff changeset
304 n, err := ReadFull(r, buf)
kono
parents:
diff changeset
305 if err != nil && err != ErrUnexpectedEOF {
kono
parents:
diff changeset
306 t.Fatalf("got: %q; want: %q", err, ErrUnexpectedEOF)
kono
parents:
diff changeset
307 }
kono
parents:
diff changeset
308 result = string(buf[0:n])
kono
parents:
diff changeset
309 <-done
kono
parents:
diff changeset
310
kono
parents:
diff changeset
311 if result != "hello" {
kono
parents:
diff changeset
312 t.Errorf("got: %q; want: %q", result, "hello")
kono
parents:
diff changeset
313 }
kono
parents:
diff changeset
314 if writeErr != ErrClosedPipe {
kono
parents:
diff changeset
315 t.Errorf("got: %q; want: %q", writeErr, ErrClosedPipe)
kono
parents:
diff changeset
316 }
kono
parents:
diff changeset
317 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
318
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
319 func TestPipeCloseError(t *testing.T) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
320 type testError1 struct{ error }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
321 type testError2 struct{ error }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
322
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
323 r, w := Pipe()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
324 r.CloseWithError(testError1{})
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
325 if _, err := w.Write(nil); err != (testError1{}) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
326 t.Errorf("Write error: got %T, want testError1", err)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
327 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
328 r.CloseWithError(testError2{})
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
329 if _, err := w.Write(nil); err != (testError1{}) {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
330 t.Errorf("Write error: got %T, want testError1", err)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
331 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
332
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
333 r, w = Pipe()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
334 w.CloseWithError(testError1{})
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
335 if _, err := r.Read(nil); err != (testError1{}) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
336 t.Errorf("Read error: got %T, want testError1", err)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
337 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
338 w.CloseWithError(testError2{})
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
339 if _, err := r.Read(nil); err != (testError1{}) {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
340 t.Errorf("Read error: got %T, want testError1", err)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
341 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
342 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
343
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
344 func TestPipeConcurrent(t *testing.T) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
345 const (
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
346 input = "0123456789abcdef"
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
347 count = 8
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
348 readSize = 2
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
349 )
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
350
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
351 t.Run("Write", func(t *testing.T) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
352 r, w := Pipe()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
353
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
354 for i := 0; i < count; i++ {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
355 go func() {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
356 time.Sleep(time.Millisecond) // Increase probability of race
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
357 if n, err := w.Write([]byte(input)); n != len(input) || err != nil {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
358 t.Errorf("Write() = (%d, %v); want (%d, nil)", n, err, len(input))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
359 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
360 }()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
361 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
362
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
363 buf := make([]byte, count*len(input))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
364 for i := 0; i < len(buf); i += readSize {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
365 if n, err := r.Read(buf[i : i+readSize]); n != readSize || err != nil {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
366 t.Errorf("Read() = (%d, %v); want (%d, nil)", n, err, readSize)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
367 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
368 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
369
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
370 // Since each Write is fully gated, if multiple Read calls were needed,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
371 // the contents of Write should still appear together in the output.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
372 got := string(buf)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
373 want := strings.Repeat(input, count)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
374 if got != want {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
375 t.Errorf("got: %q; want: %q", got, want)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
376 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
377 })
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
378
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
379 t.Run("Read", func(t *testing.T) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
380 r, w := Pipe()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
381
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
382 c := make(chan []byte, count*len(input)/readSize)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
383 for i := 0; i < cap(c); i++ {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
384 go func() {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
385 time.Sleep(time.Millisecond) // Increase probability of race
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
386 buf := make([]byte, readSize)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
387 if n, err := r.Read(buf); n != readSize || err != nil {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
388 t.Errorf("Read() = (%d, %v); want (%d, nil)", n, err, readSize)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
389 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
390 c <- buf
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
391 }()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
392 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
393
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
394 for i := 0; i < count; i++ {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
395 if n, err := w.Write([]byte(input)); n != len(input) || err != nil {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
396 t.Errorf("Write() = (%d, %v); want (%d, nil)", n, err, len(input))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
397 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
398 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
399
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
400 // Since each read is independent, the only guarantee about the output
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
401 // is that it is a permutation of the input in readSized groups.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
402 got := make([]byte, 0, count*len(input))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
403 for i := 0; i < cap(c); i++ {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
404 got = append(got, (<-c)...)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
405 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
406 got = sortBytesInGroups(got, readSize)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
407 want := bytes.Repeat([]byte(input), count)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
408 want = sortBytesInGroups(want, readSize)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
409 if string(got) != string(want) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
410 t.Errorf("got: %q; want: %q", got, want)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
411 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
412 })
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
413 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
414
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
415 func sortBytesInGroups(b []byte, n int) []byte {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
416 var groups [][]byte
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
417 for len(b) > 0 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
418 groups = append(groups, b[:n])
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
419 b = b[n:]
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
420 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
421 sort.Slice(groups, func(i, j int) bool { return bytes.Compare(groups[i], groups[j]) < 0 })
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
422 return bytes.Join(groups, nil)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
423 }