Skip to content

Commit 8ad9a58

Browse files
committed
add io helper
1 parent f9d0cb0 commit 8ad9a58

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

io.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package helpers
2+
3+
import (
4+
"io"
5+
"time"
6+
)
7+
8+
// ReadWithTimeout reads data until it gets the desired number of bytes or times out.
9+
//
10+
// This is an inefficient implementation that should only be used in tests.
11+
func ReadWithTimeout(r io.Reader, n int, timeout time.Duration) []byte {
12+
byteCh := make(chan byte)
13+
closer := make(chan struct{})
14+
15+
go func() {
16+
count := 0
17+
for {
18+
select {
19+
case <-closer:
20+
return
21+
default:
22+
b := make([]byte, 1)
23+
got, err := r.Read(b)
24+
if err != nil {
25+
return
26+
}
27+
if got > 0 {
28+
byteCh <- b[0]
29+
}
30+
count++
31+
if count >= n {
32+
return
33+
}
34+
}
35+
}
36+
}()
37+
38+
buf := make([]byte, 0, n)
39+
deadline := time.After(timeout)
40+
41+
ReadLoop:
42+
for {
43+
select {
44+
case b := <-byteCh:
45+
buf = append(buf, b)
46+
if len(buf) >= n {
47+
break ReadLoop
48+
}
49+
case <-deadline:
50+
break ReadLoop
51+
}
52+
}
53+
close(closer)
54+
return buf
55+
}

io_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package helpers
2+
3+
import (
4+
"bytes"
5+
"io"
6+
"testing"
7+
"time"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestReadWithTimeout(t *testing.T) {
13+
var buf1 bytes.Buffer
14+
data := ReadWithTimeout(&buf1, 5, time.Millisecond*50)
15+
assert.Len(t, data, 0)
16+
17+
var buf2 bytes.Buffer
18+
buf2.WriteString("he")
19+
data = ReadWithTimeout(&buf2, 5, time.Millisecond*50)
20+
assert.Equal(t, "he", string(data))
21+
22+
var buf3 bytes.Buffer
23+
buf3.WriteString("hello")
24+
data = ReadWithTimeout(&buf3, 5, time.Millisecond*50)
25+
assert.Equal(t, "hello", string(data))
26+
27+
r1, w1 := io.Pipe()
28+
go func() {
29+
w1.Write([]byte("good"))
30+
time.Sleep(10 * time.Millisecond)
31+
w1.Write([]byte("bye"))
32+
}()
33+
data = ReadWithTimeout(r1, 7, time.Millisecond*100)
34+
assert.Equal(t, "goodbye", string(data))
35+
36+
r2, w2 := io.Pipe()
37+
go func() {
38+
w2.Write([]byte("good"))
39+
}()
40+
data = ReadWithTimeout(r2, 7, time.Millisecond*100)
41+
time.Sleep(time.Millisecond * 100)
42+
assert.Equal(t, "good", string(data))
43+
}

0 commit comments

Comments
 (0)