Allow coarrays in select type. [PR46371, PR56496]
[official-gcc.git] / libgo / go / net / writev_test.go
blob18795a457ac1f6a4066fc6b72a827f282c43820d
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.
5 //go:build !js
7 package net
9 import (
10 "bytes"
11 "fmt"
12 "internal/poll"
13 "io"
14 "reflect"
15 "runtime"
16 "sync"
17 "testing"
20 func TestBuffers_read(t *testing.T) {
21 const story = "once upon a time in Gopherland ... "
22 buffers := Buffers{
23 []byte("once "),
24 []byte("upon "),
25 []byte("a "),
26 []byte("time "),
27 []byte("in "),
28 []byte("Gopherland ... "),
30 got, err := io.ReadAll(&buffers)
31 if err != nil {
32 t.Fatal(err)
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) {
43 tests := []struct {
44 in Buffers
45 consume int64
46 want Buffers
49 in: Buffers{[]byte("foo"), []byte("bar")},
50 consume: 0,
51 want: Buffers{[]byte("foo"), []byte("bar")},
54 in: Buffers{[]byte("foo"), []byte("bar")},
55 consume: 2,
56 want: Buffers{[]byte("o"), []byte("bar")},
59 in: Buffers{[]byte("foo"), []byte("bar")},
60 consume: 3,
61 want: Buffers{[]byte("bar")},
64 in: Buffers{[]byte("foo"), []byte("bar")},
65 consume: 4,
66 want: Buffers{[]byte("ar")},
69 in: Buffers{nil, nil, nil, []byte("bar")},
70 consume: 1,
71 want: Buffers{[]byte("ar")},
74 in: Buffers{nil, nil, nil, []byte("foo")},
75 consume: 0,
76 want: Buffers{[]byte("foo")},
79 in: Buffers{nil, nil, nil},
80 consume: 0,
81 want: Buffers{},
84 for i, tt := range tests {
85 in := tt.in
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 {
107 sync.Mutex
108 log []int
110 poll.TestHookDidWritev = func(size int) {
111 writeLog.Lock()
112 writeLog.log = append(writeLog.log, size)
113 writeLog.Unlock()
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]
125 var n int64
126 var err error
127 if useCopy {
128 n, err = io.Copy(c, &buffers)
129 } else {
130 n, err = buffers.WriteTo(c)
132 if err != nil {
133 return err
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())
141 return nil
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
149 var gotSum int
150 for _, v := range writeLog.log {
151 gotSum += v
154 var wantSum int
155 switch runtime.GOOS {
156 case "android", "darwin", "ios", "dragonfly", "freebsd", "illumos", "linux", "netbsd", "openbsd":
157 var wantMinCalls int
158 wantSum = want.Len()
159 v := chunks
160 for v > 0 {
161 wantMinCalls++
162 v -= 1024
164 if len(writeLog.log) < wantMinCalls {
165 t.Errorf("write calls = %v < wanted min %v", len(writeLog.log), wantMinCalls)
167 case "windows":
168 var wantCalls int
169 wantSum = want.Len()
170 if wantSum > 0 {
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)
180 return nil
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")
190 defer ln.Close()
192 ch := make(chan Conn, 1)
193 go func() {
194 defer close(ch)
195 c, err := ln.Accept()
196 if err != nil {
197 t.Error(err)
198 return
200 ch <- c
202 c1, err := Dial("tcp", ln.Addr().String())
203 if err != nil {
204 t.Fatal(err)
206 defer c1.Close()
207 c2 := <-ch
208 if c2 == nil {
209 t.Fatal("no server side connection")
211 c2.Close()
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 {
219 buffers[i] = buf
221 if _, err := buffers.WriteTo(c1); err == nil {
222 t.Fatal("Buffers.WriteTo(closed conn) succeeded, want error")