diff options
author | Ting-Yu Wang <anivia@google.com> | 2021-01-07 14:14:58 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-01-07 14:17:18 -0800 |
commit | b1de1da318631c6d29f6c04dea370f712078f443 (patch) | |
tree | b4e7f8f1b8fd195fa5d16257c5687126e1c7c9f6 /pkg/tcpip/buffer/view_test.go | |
parent | f4b4ed666d13eef6aebe23189b1431a933de0d8e (diff) |
netstack: Refactor tcpip.Endpoint.Read
Read now takes a destination io.Writer, count, options. Keeping the method name
Read, in contrast to the Write method.
This enables:
* direct transfer of views under VV
* zero copy
It also eliminates the need for sentry to keep a slice of view because
userspace had requested a read that is smaller than the view returned, removing
the complexity there.
Read/Peek/ReadPacket are now consolidated together and some duplicate code is
removed.
PiperOrigin-RevId: 350636322
Diffstat (limited to 'pkg/tcpip/buffer/view_test.go')
-rw-r--r-- | pkg/tcpip/buffer/view_test.go | 68 |
1 files changed, 59 insertions, 9 deletions
diff --git a/pkg/tcpip/buffer/view_test.go b/pkg/tcpip/buffer/view_test.go index 726e54de9..e0ef8a94d 100644 --- a/pkg/tcpip/buffer/view_test.go +++ b/pkg/tcpip/buffer/view_test.go @@ -235,14 +235,16 @@ func TestToClone(t *testing.T) { } } -func TestVVReadToVV(t *testing.T) { - testCases := []struct { - comment string - vv VectorisedView - bytesToRead int - wantBytes string - leftVV VectorisedView - }{ +type readToTestCases struct { + comment string + vv VectorisedView + bytesToRead int + wantBytes string + leftVV VectorisedView +} + +func createReadToTestCases() []readToTestCases { + return []readToTestCases{ { comment: "large VV, short read", vv: vv(30, "012345678901234567890123456789"), @@ -279,8 +281,10 @@ func TestVVReadToVV(t *testing.T) { leftVV: vv(0, ""), }, } +} - for _, tc := range testCases { +func TestVVReadToVV(t *testing.T) { + for _, tc := range createReadToTestCases() { t.Run(tc.comment, func(t *testing.T) { var readTo VectorisedView inSize := tc.vv.Size() @@ -301,6 +305,52 @@ func TestVVReadToVV(t *testing.T) { } } +func TestVVReadTo(t *testing.T) { + for _, tc := range createReadToTestCases() { + t.Run(tc.comment, func(t *testing.T) { + var dst bytes.Buffer + origSize := tc.vv.Size() + copied, err := tc.vv.ReadTo(&dst, tc.bytesToRead, false /* peek */) + if got, want := copied, len(tc.wantBytes); err != nil || got != want { + t.Errorf("got ReadTo(&dst, %d, false) = %d, %v; want %d, nil", tc.bytesToRead, got, err, want) + } + if got, want := string(dst.Bytes()), tc.wantBytes; got != want { + t.Errorf("got dst = %q, want %q", got, want) + } + if got, want := tc.vv.Size(), origSize-copied; got != want { + t.Errorf("got after-read tc.vv.Size() = %d, want %d", got, want) + } + if got, want := string(tc.vv.ToView()), string(tc.leftVV.ToView()); got != want { + t.Errorf("got after-read data in tc.vv = %q, want %q", got, want) + } + }) + } +} + +func TestVVReadToPeek(t *testing.T) { + for _, tc := range createReadToTestCases() { + t.Run(tc.comment, func(t *testing.T) { + var dst bytes.Buffer + origSize := tc.vv.Size() + origData := string(tc.vv.ToView()) + copied, err := tc.vv.ReadTo(&dst, tc.bytesToRead, true /* peek */) + if got, want := copied, len(tc.wantBytes); err != nil || got != want { + t.Errorf("got ReadTo(&dst, %d, false) = %d, %v; want %d, nil", tc.bytesToRead, got, err, want) + } + if got, want := string(dst.Bytes()), tc.wantBytes; got != want { + t.Errorf("got dst = %q, want %q", got, want) + } + // Expect tc.vv is unchanged. + if got, want := tc.vv.Size(), origSize; got != want { + t.Errorf("got after-read tc.vv.Size() = %d, want %d", got, want) + } + if got, want := string(tc.vv.ToView()), origData; got != want { + t.Errorf("got after-read data in tc.vv = %q, want %q", got, want) + } + }) + } +} + func TestVVRead(t *testing.T) { testCases := []struct { comment string |