1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
20 func TestBuffers_read(t
*testing
.T
) {
21 const story
= "once upon a time in Gopherland ... "
28 []byte("Gopherland ... "),
30 got
, err
:= io
.ReadAll(&buffers
)
34 if string(got
) != story
{
35 t
.Errorf("read %q; want %q", got
, story
)
37 if len(buffers
) != 0 {
38 t
.Errorf("len(buffers) = %d; want 0", len(buffers
))
42 func TestBuffers_consume(t
*testing
.T
) {
49 in
: Buffers
{[]byte("foo"), []byte("bar")},
51 want
: Buffers
{[]byte("foo"), []byte("bar")},
54 in
: Buffers
{[]byte("foo"), []byte("bar")},
56 want
: Buffers
{[]byte("o"), []byte("bar")},
59 in
: Buffers
{[]byte("foo"), []byte("bar")},
61 want
: Buffers
{[]byte("bar")},
64 in
: Buffers
{[]byte("foo"), []byte("bar")},
66 want
: Buffers
{[]byte("ar")},
69 in
: Buffers
{nil, nil, nil, []byte("bar")},
71 want
: Buffers
{[]byte("ar")},
74 in
: Buffers
{nil, nil, nil, []byte("foo")},
76 want
: Buffers
{[]byte("foo")},
79 in
: Buffers
{nil, nil, nil},
84 for i
, tt
:= range tests
{
86 in
.consume(tt
.consume
)
87 if !reflect
.DeepEqual(in
, tt
.want
) {
88 t
.Errorf("%d. after consume(%d) = %+v, want %+v", i
, tt
.consume
, in
, tt
.want
)
93 func TestBuffers_WriteTo(t
*testing
.T
) {
94 for _
, name
:= range []string{"WriteTo", "Copy"} {
95 for _
, size
:= range []int{0, 10, 1023, 1024, 1025} {
96 t
.Run(fmt
.Sprintf("%s/%d", name
, size
), func(t
*testing
.T
) {
97 testBuffer_writeTo(t
, size
, name
== "Copy")
103 func testBuffer_writeTo(t
*testing
.T
, chunks
int, useCopy
bool) {
104 oldHook
:= poll
.TestHookDidWritev
105 defer func() { poll
.TestHookDidWritev
= oldHook
}()
106 var writeLog
struct {
110 poll
.TestHookDidWritev
= func(size
int) {
112 writeLog
.log
= append(writeLog
.log
, size
)
115 var want bytes
.Buffer
116 for i
:= 0; i
< chunks
; i
++ {
117 want
.WriteByte(byte(i
))
120 withTCPConnPair(t
, func(c
*TCPConn
) error
{
121 buffers
:= make(Buffers
, chunks
)
122 for i
:= range buffers
{
123 buffers
[i
] = want
.Bytes()[i
: i
+1]
128 n
, err
= io
.Copy(c
, &buffers
)
130 n
, err
= buffers
.WriteTo(c
)
135 if len(buffers
) != 0 {
136 return fmt
.Errorf("len(buffers) = %d; want 0", len(buffers
))
138 if n
!= int64(want
.Len()) {
139 return fmt
.Errorf("Buffers.WriteTo returned %d; want %d", n
, want
.Len())
142 }, func(c
*TCPConn
) error
{
143 all
, err
:= io
.ReadAll(c
)
144 if !bytes
.Equal(all
, want
.Bytes()) || err
!= nil {
145 return fmt
.Errorf("client read %q, %v; want %q, nil", all
, err
, want
.Bytes())
148 writeLog
.Lock() // no need to unlock
150 for _
, v
:= range writeLog
.log
{
155 switch runtime
.GOOS
{
156 case "android", "darwin", "ios", "dragonfly", "freebsd", "illumos", "linux", "netbsd", "openbsd":
164 if len(writeLog
.log
) < wantMinCalls
{
165 t
.Errorf("write calls = %v < wanted min %v", len(writeLog
.log
), wantMinCalls
)
171 wantCalls
= 1 // windows will always do 1 syscall, unless sending empty buffer
173 if len(writeLog
.log
) != wantCalls
{
174 t
.Errorf("write calls = %v; want %v", len(writeLog
.log
), wantCalls
)
177 if gotSum
!= wantSum
{
178 t
.Errorf("writev call sum = %v; want %v", gotSum
, wantSum
)
184 func TestWritevError(t
*testing
.T
) {
185 if runtime
.GOOS
== "windows" {
186 t
.Skipf("skipping the test: windows does not have problem sending large chunks of data")
189 ln
:= newLocalListener(t
, "tcp")
192 ch
:= make(chan Conn
, 1)
195 c
, err
:= ln
.Accept()
202 c1
, err
:= Dial("tcp", ln
.Addr().String())
209 t
.Fatal("no server side connection")
213 // 1 GB of data should be enough to notice the connection is gone.
214 // Just a few bytes is not enough.
215 // Arrange to reuse the same 1 MB buffer so that we don't allocate much.
216 buf
:= make([]byte, 1<<20)
217 buffers
:= make(Buffers
, 1<<10)
218 for i
:= range buffers
{
221 if _
, err
:= buffers
.WriteTo(c1
); err
== nil {
222 t
.Fatal("Buffers.WriteTo(closed conn) succeeded, want error")