func TestClientSendReadError(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() ch, r := iotest.ChunkReader() ch <- []byte{0x00, 0x00} ch <- nil w := NewMockWriter(mockCtrl) w.EXPECT().Write(gomock.Any()).Return(10, nil) client := NewClient(w, r) _, err := client.Send([]byte{}) assert.Equal(t, iotest.ErrUser, err) }
func TestServeReadError(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() ch, r := iotest.ChunkReader() ch <- []byte{0x00, 0x00} ch <- nil w := NewMockWriteCloser(mockCtrl) w.EXPECT().Close().Return(nil) server := NewServer(r, w) err := server.Serve(handlerFunc( func([]byte) ([]byte, error) { return nil, errors.New("unexpected call") }, )) assert.Equal(t, iotest.ErrUser, err) }
func TestReader(t *testing.T) { type wantRead struct { frame []byte err error } tests := []struct { desc string giveReader func() io.Reader wantReads []wantRead // reads to perform and what to expect // if non-zero, the _fastPathFrameSize will be set to this value for the test fastPathThreshold int64 }{ { desc: "error while reading length", giveReader: func() io.Reader { ch, reader := iotest.ChunkReader() // one successful read ch <- []byte{0x00, 0x00, 0x00, 0x01, 0x01} // error half way through reading the length ch <- []byte{0x00, 0x00} ch <- nil return reader }, wantReads: []wantRead{ {frame: []byte{0x01}}, {err: iotest.ErrUser}, }, }, { desc: "fast path, no errors", giveReader: func() io.Reader { return bytes.NewReader([]byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x01, 0x02, 0x00, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, }) }, wantReads: []wantRead{ {frame: []byte{}}, {frame: []byte{0x01}}, {frame: []byte{0x01, 0x02}}, {frame: []byte{0x01, 0x02, 0x03}}, }, }, { desc: "fast path, error while reading body", giveReader: func() io.Reader { ch, reader := iotest.ChunkReader() // one successful read ch <- []byte{0x00, 0x00, 0x00, 0x01, 0x01} // error while reading the body ch <- []byte{0x00, 0x00, 0x00, 0x10} ch <- []byte{0x01, 0x02, 0x03, 0x04, 0x05} ch <- nil return reader }, wantReads: []wantRead{ {frame: []byte{0x01}}, {err: iotest.ErrUser}, }, }, { desc: "slow path, no errors", giveReader: func() io.Reader { return bytes.NewReader([]byte{ 0x00, 0x00, 0x00, 0x03, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x05, 0x01, 0x02, 0x03, 0x04, 0x05, }) }, wantReads: []wantRead{ {frame: []byte{0x01, 0x02, 0x03}}, {frame: []byte{0x01, 0x02, 0x03, 0x04}}, {frame: []byte{0x01, 0x02, 0x03, 0x04, 0x05}}, }, fastPathThreshold: 3, }, { desc: "slow path, error while reading body", giveReader: func() io.Reader { ch, reader := iotest.ChunkReader() ch <- []byte{0x1f, 0x40, 0x00, 0x00} // 500 MB ch <- []byte{0x00, 0x00, 0x00, 0x00} ch <- nil return reader }, wantReads: []wantRead{ {err: iotest.ErrUser}, }, }, { desc: "slow path, body too short", giveReader: func() io.Reader { ch, reader := iotest.ChunkReader() ch <- []byte{0x1f, 0x40, 0x00, 0x00} // 500 MB ch <- []byte{0x00} close(ch) return reader }, wantReads: []wantRead{ {err: io.EOF}, }, }, } for _, tt := range tests { func() { if tt.fastPathThreshold != 0 { reset := setFastPathThreshold(tt.fastPathThreshold) defer reset() } r := NewReader(tt.giveReader()) for _, want := range tt.wantReads { frame, err := r.Read() if want.frame != nil && assert.NoError(t, err, tt.desc) { assert.Equal(t, want.frame, frame, tt.desc) } else if assert.Error(t, err, tt.desc) { assert.Equal(t, want.err, err, tt.desc) } } assert.NoError(t, r.Close(), tt.desc) }() } }