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.
19 func TestBuffers_read(t *testing.T) {
20 const story = "once upon a time in Gopherland ... "
27 []byte("Gopherland ... "),
29 got, err := ioutil.ReadAll(&buffers)
33 if string(got) != story {
34 t.Errorf("read %q; want %q", got, story)
36 if len(buffers) != 0 {
37 t.Errorf("len(buffers) = %d; want 0", len(buffers))
41 func TestBuffers_consume(t *testing.T) {
48 in: Buffers{[]byte("foo"), []byte("bar")},
50 want: Buffers{[]byte("foo"), []byte("bar")},
53 in: Buffers{[]byte("foo"), []byte("bar")},
55 want: Buffers{[]byte("o"), []byte("bar")},
58 in: Buffers{[]byte("foo"), []byte("bar")},
60 want: Buffers{[]byte("bar")},
63 in: Buffers{[]byte("foo"), []byte("bar")},
65 want: Buffers{[]byte("ar")},
68 in: Buffers{nil, nil, nil, []byte("bar")},
70 want: Buffers{[]byte("ar")},
73 in: Buffers{nil, nil, nil, []byte("foo")},
75 want: Buffers{[]byte("foo")},
78 in: Buffers{nil, nil, nil},
83 for i, tt := range tests {
85 in.consume(tt.consume)
86 if !reflect.DeepEqual(in, tt.want) {
87 t.Errorf("%d. after consume(%d) = %+v, want %+v", i, tt.consume, in, tt.want)
92 func TestBuffers_WriteTo(t *testing.T) {
93 for _, name := range []string{"WriteTo", "Copy"} {
94 for _, size := range []int{0, 10, 1023, 1024, 1025} {
95 t.Run(fmt.Sprintf("%s/%d", name, size), func(t *testing.T) {
96 testBuffer_writeTo(t, size, name == "Copy")
102 func testBuffer_writeTo(t *testing.T, chunks int, useCopy bool) {
103 oldHook := poll.TestHookDidWritev
104 defer func() { poll.TestHookDidWritev = oldHook }()
105 var writeLog struct {
109 poll.TestHookDidWritev = func(size int) {
111 writeLog.log = append(writeLog.log, size)
114 var want bytes.Buffer
115 for i := 0; i < chunks; i++ {
116 want.WriteByte(byte(i))
119 withTCPConnPair(t, func(c *TCPConn) error {
120 buffers := make(Buffers, chunks)
121 for i := range buffers {
122 buffers[i] = want.Bytes()[i : i+1]
127 n, err = io.Copy(c, &buffers)
129 n, err = buffers.WriteTo(c)
134 if len(buffers) != 0 {
135 return fmt.Errorf("len(buffers) = %d; want 0", len(buffers))
137 if n != int64(want.Len()) {
138 return fmt.Errorf("Buffers.WriteTo returned %d; want %d", n, want.Len())
141 }, func(c *TCPConn) error {
142 all, err := ioutil.ReadAll(c)
143 if !bytes.Equal(all, want.Bytes()) || err != nil {
144 return fmt.Errorf("client read %q, %v; want %q, nil", all, err, want.Bytes())
147 writeLog.Lock() // no need to unlock
149 for _, v := range writeLog.log {
154 switch runtime.GOOS {
155 case "android", "darwin", "dragonfly", "freebsd", "linux", "netbsd", "openbsd":
163 if len(writeLog.log) < wantMinCalls {
164 t.Errorf("write calls = %v < wanted min %v", len(writeLog.log), wantMinCalls)
170 wantCalls = 1 // windows will always do 1 syscall, unless sending empty buffer
172 if len(writeLog.log) != wantCalls {
173 t.Errorf("write calls = %v; want %v", len(writeLog.log), wantCalls)
176 if gotSum != wantSum {
177 t.Errorf("writev call sum = %v; want %v", gotSum, wantSum)
183 func TestWritevError(t *testing.T) {
184 if runtime.GOOS == "windows" {
185 t.Skipf("skipping the test: windows does not have problem sending large chunks of data")
188 ln, err := newLocalListener("tcp")
194 ch := make(chan Conn, 1)
197 c, err := ln.Accept()
204 c1, err := Dial("tcp", ln.Addr().String())
211 t.Fatal("no server side connection")
215 // 1 GB of data should be enough to notice the connection is gone.
216 // Just a few bytes is not enough.
217 // Arrange to reuse the same 1 MB buffer so that we don't allocate much.
218 buf := make([]byte, 1<<20)
219 buffers := make(Buffers, 1<<10)
220 for i := range buffers {
223 if _, err := buffers.WriteTo(c1); err == nil {
224 t.Fatal("Buffers.WriteTo(closed conn) succeeded, want error")