2016-07-13 20:37:03 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
2017-09-19 12:59:05 +00:00
|
|
|
"fmt"
|
2016-07-13 20:37:03 +00:00
|
|
|
"io"
|
|
|
|
"reflect"
|
2017-09-19 12:59:05 +00:00
|
|
|
"strings"
|
2016-07-13 20:37:03 +00:00
|
|
|
"testing"
|
2016-07-20 02:48:16 +00:00
|
|
|
"time"
|
2016-07-13 20:37:03 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestFS_FrameReader(t *testing.T) {
|
2017-07-21 23:33:04 +00:00
|
|
|
t.Parallel()
|
2016-07-13 20:37:03 +00:00
|
|
|
// Create a channel of the frames and a cancel channel
|
|
|
|
framesCh := make(chan *StreamFrame, 3)
|
2017-09-19 12:59:05 +00:00
|
|
|
errCh := make(chan error)
|
2016-07-13 20:37:03 +00:00
|
|
|
cancelCh := make(chan struct{})
|
|
|
|
|
2017-09-19 12:59:05 +00:00
|
|
|
r := NewFrameReader(framesCh, errCh, cancelCh)
|
2016-07-13 20:37:03 +00:00
|
|
|
|
|
|
|
// Create some frames and send them
|
|
|
|
f1 := &StreamFrame{
|
|
|
|
File: "foo",
|
2016-07-13 21:33:17 +00:00
|
|
|
Offset: 5,
|
2016-07-13 20:37:03 +00:00
|
|
|
Data: []byte("hello"),
|
|
|
|
}
|
|
|
|
f2 := &StreamFrame{
|
|
|
|
File: "foo",
|
2016-07-13 21:33:17 +00:00
|
|
|
Offset: 10,
|
2016-07-13 20:37:03 +00:00
|
|
|
Data: []byte(", wor"),
|
|
|
|
}
|
|
|
|
f3 := &StreamFrame{
|
|
|
|
File: "foo",
|
2016-07-13 21:33:17 +00:00
|
|
|
Offset: 12,
|
2016-07-13 20:37:03 +00:00
|
|
|
Data: []byte("ld"),
|
|
|
|
}
|
|
|
|
framesCh <- f1
|
|
|
|
framesCh <- f2
|
|
|
|
framesCh <- f3
|
|
|
|
close(framesCh)
|
|
|
|
|
|
|
|
expected := []byte("hello, world")
|
|
|
|
|
|
|
|
// Read a little
|
|
|
|
p := make([]byte, 12)
|
|
|
|
|
|
|
|
n, err := r.Read(p[:5])
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Read failed: %v", err)
|
|
|
|
}
|
|
|
|
if off := r.Offset(); off != n {
|
|
|
|
t.Fatalf("unexpected read bytes: got %v; wanted %v", n, off)
|
|
|
|
}
|
|
|
|
|
|
|
|
off := n
|
|
|
|
for {
|
|
|
|
n, err = r.Read(p[off:])
|
|
|
|
if err != nil {
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
t.Fatalf("Read failed: %v", err)
|
|
|
|
}
|
|
|
|
off += n
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(p, expected) {
|
|
|
|
t.Fatalf("read %q, wanted %q", string(p), string(expected))
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := r.Close(); err != nil {
|
|
|
|
t.Fatalf("Close() failed: %v", err)
|
|
|
|
}
|
|
|
|
if _, ok := <-cancelCh; ok {
|
|
|
|
t.Fatalf("Close() didn't close cancel channel")
|
|
|
|
}
|
|
|
|
if len(expected) != r.Offset() {
|
|
|
|
t.Fatalf("offset %d, wanted %d", r.Offset(), len(expected))
|
|
|
|
}
|
|
|
|
}
|
2016-07-20 02:48:16 +00:00
|
|
|
|
|
|
|
func TestFS_FrameReader_Unblock(t *testing.T) {
|
2017-07-21 23:33:04 +00:00
|
|
|
t.Parallel()
|
2016-07-20 02:48:16 +00:00
|
|
|
// Create a channel of the frames and a cancel channel
|
|
|
|
framesCh := make(chan *StreamFrame, 3)
|
2017-09-19 12:59:05 +00:00
|
|
|
errCh := make(chan error)
|
2016-07-20 02:48:16 +00:00
|
|
|
cancelCh := make(chan struct{})
|
|
|
|
|
2017-09-19 12:59:05 +00:00
|
|
|
r := NewFrameReader(framesCh, errCh, cancelCh)
|
2016-07-20 02:48:16 +00:00
|
|
|
r.SetUnblockTime(10 * time.Millisecond)
|
|
|
|
|
|
|
|
// Read a little
|
|
|
|
p := make([]byte, 12)
|
|
|
|
|
|
|
|
n, err := r.Read(p)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Read failed: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n != 0 {
|
|
|
|
t.Fatalf("should have unblocked")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unset the unblock
|
|
|
|
r.SetUnblockTime(0)
|
|
|
|
|
|
|
|
resultCh := make(chan struct{})
|
|
|
|
go func() {
|
|
|
|
r.Read(p)
|
|
|
|
close(resultCh)
|
|
|
|
}()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-resultCh:
|
|
|
|
t.Fatalf("shouldn't have unblocked")
|
|
|
|
case <-time.After(300 * time.Millisecond):
|
|
|
|
}
|
|
|
|
}
|
2017-09-19 12:59:05 +00:00
|
|
|
|
|
|
|
func TestFS_FrameReader_Error(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
// Create a channel of the frames and a cancel channel
|
|
|
|
framesCh := make(chan *StreamFrame, 3)
|
|
|
|
errCh := make(chan error, 1)
|
|
|
|
cancelCh := make(chan struct{})
|
|
|
|
|
|
|
|
r := NewFrameReader(framesCh, errCh, cancelCh)
|
|
|
|
r.SetUnblockTime(10 * time.Millisecond)
|
|
|
|
|
|
|
|
// Send an error
|
|
|
|
expected := fmt.Errorf("test error")
|
|
|
|
errCh <- expected
|
|
|
|
|
|
|
|
// Read a little
|
|
|
|
p := make([]byte, 12)
|
|
|
|
|
|
|
|
_, err := r.Read(p)
|
|
|
|
if err == nil || !strings.Contains(err.Error(), expected.Error()) {
|
|
|
|
t.Fatalf("bad error: %v", err)
|
|
|
|
}
|
|
|
|
}
|