Write stream implementation (#19)
Defines a WriteStream structure for buffering writes, similar to the existing ReadStream. WriteStreams can be created on OutEndpoints by using ep.NewStream().
This commit is contained in:
@@ -62,7 +62,7 @@ func (f *fakeStreamTransfer) wait() (int, error) {
|
||||
return 0, errors.New("wait() called on a free()d transfer")
|
||||
}
|
||||
if !f.inFlight {
|
||||
return 0, errors.New("wait() called without submit()")
|
||||
return 0, nil
|
||||
}
|
||||
if len(f.res) == 0 {
|
||||
return 0, errors.New("wait() called but fake result missing")
|
||||
@@ -224,7 +224,8 @@ func TestTransferReadStream(t *testing.T) {
|
||||
}
|
||||
tt[i] = ftt[i]
|
||||
}
|
||||
s := ReadStream{newStream(tt, true)}
|
||||
s := ReadStream{s: newStream(tt)}
|
||||
s.s.submitAll()
|
||||
buf := make([]byte, 400)
|
||||
got := make([]readRes, len(tc.want))
|
||||
for i := range tc.want {
|
||||
@@ -250,3 +251,106 @@ func TestTransferReadStream(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransferWriteStream(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, tc := range []struct {
|
||||
desc string
|
||||
transfers [][]fakeStreamResult
|
||||
writes []int
|
||||
want []int
|
||||
total int
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "successful two transfers",
|
||||
transfers: [][]fakeStreamResult{
|
||||
{{n: 1500}},
|
||||
{{n: 1500}},
|
||||
{{n: 1500}},
|
||||
},
|
||||
writes: []int{3000},
|
||||
want: []int{3000},
|
||||
total: 3000,
|
||||
},
|
||||
{
|
||||
desc: "submit failed on second transfer",
|
||||
transfers: [][]fakeStreamResult{
|
||||
{{n: 1500}},
|
||||
{{submitErr: errSentinel}},
|
||||
{{n: 1500}},
|
||||
},
|
||||
writes: []int{3000},
|
||||
want: []int{1500},
|
||||
total: 1500,
|
||||
err: errSentinel,
|
||||
},
|
||||
{
|
||||
desc: "wait failed on second transfer",
|
||||
transfers: [][]fakeStreamResult{
|
||||
{{n: 1500}},
|
||||
{{waitErr: errSentinel}},
|
||||
{{n: 1500}},
|
||||
},
|
||||
writes: []int{3000, 1500},
|
||||
want: []int{3000, 1500},
|
||||
total: 1500,
|
||||
err: errSentinel,
|
||||
},
|
||||
{
|
||||
desc: "reused transfer",
|
||||
transfers: [][]fakeStreamResult{
|
||||
{{n: 1500}, {n: 1500}},
|
||||
{{n: 1500}, {n: 1500}},
|
||||
{{n: 1500}, {n: 500}},
|
||||
},
|
||||
writes: []int{3000, 3000, 2000},
|
||||
want: []int{3000, 3000, 2000},
|
||||
total: 8000,
|
||||
},
|
||||
{
|
||||
desc: "wait failed on reused transfer",
|
||||
transfers: [][]fakeStreamResult{
|
||||
{{n: 1500}, {n: 1500}},
|
||||
{{waitErr: errSentinel}, {n: 1500}},
|
||||
{{n: 1500}, {n: 1500}},
|
||||
},
|
||||
writes: []int{1500, 1500, 1500, 1500, 1500},
|
||||
want: []int{1500, 1500, 1500, 1500, 0},
|
||||
total: 1500,
|
||||
err: errSentinel,
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ftt := make([]*fakeStreamTransfer, len(tc.transfers))
|
||||
tt := make([]transferIntf, len(tc.transfers))
|
||||
for i := range tc.transfers {
|
||||
ftt[i] = &fakeStreamTransfer{
|
||||
res: tc.transfers[i],
|
||||
}
|
||||
tt[i] = ftt[i]
|
||||
}
|
||||
s := WriteStream{s: newStream(tt)}
|
||||
for i, w := range tc.writes {
|
||||
got, err := s.Write(make([]byte, w))
|
||||
if want := tc.want[i]; got != want {
|
||||
t.Errorf("WriteStream.Write #%d: got %d, want %d", i, got, want)
|
||||
}
|
||||
if err != nil && err != tc.err {
|
||||
t.Errorf("WriteStream.Write: got error %v, want %v", err, tc.err)
|
||||
}
|
||||
}
|
||||
if err := s.Close(); err != tc.err {
|
||||
t.Fatalf("WriteStream.Close: got %v, want %v", err, tc.err)
|
||||
}
|
||||
if err := s.Close(); err != io.ErrClosedPipe {
|
||||
t.Fatalf("second WriteStream.Close: got %v, want %v", err, io.ErrClosedPipe)
|
||||
}
|
||||
if got := s.Written(); got != tc.total {
|
||||
t.Fatalf("WriteStream.Written: got %d, want %d", got, tc.total)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user