runtime: correct facilities names in s390 CPU support
[gcc.git] / libgo / go / net / sendfile_test.go
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.
4
5 // +build !js
6
7 package net
8
9 import (
10 "bytes"
11 "crypto/sha256"
12 "encoding/hex"
13 "fmt"
14 "io"
15 "io/ioutil"
16 "os"
17 "runtime"
18 "sync"
19 "testing"
20 "time"
21 )
22
23 const (
24 newton = "../testdata/Isaac.Newton-Opticks.txt"
25 newtonLen = 567198
26 newtonSHA256 = "d4a9ac22462b35e7821a4f2706c211093da678620a8f9997989ee7cf8d507bbd"
27 )
28
29 func TestSendfile(t *testing.T) {
30 ln, err := newLocalListener("tcp")
31 if err != nil {
32 t.Fatal(err)
33 }
34 defer ln.Close()
35
36 errc := make(chan error, 1)
37 go func(ln Listener) {
38 // Wait for a connection.
39 conn, err := ln.Accept()
40 if err != nil {
41 errc <- err
42 close(errc)
43 return
44 }
45
46 go func() {
47 defer close(errc)
48 defer conn.Close()
49
50 f, err := os.Open(newton)
51 if err != nil {
52 errc <- err
53 return
54 }
55 defer f.Close()
56
57 // Return file data using io.Copy, which should use
58 // sendFile if available.
59 sbytes, err := io.Copy(conn, f)
60 if err != nil {
61 errc <- err
62 return
63 }
64
65 if sbytes != newtonLen {
66 errc <- fmt.Errorf("sent %d bytes; expected %d", sbytes, newtonLen)
67 return
68 }
69 }()
70 }(ln)
71
72 // Connect to listener to retrieve file and verify digest matches
73 // expected.
74 c, err := Dial("tcp", ln.Addr().String())
75 if err != nil {
76 t.Fatal(err)
77 }
78 defer c.Close()
79
80 h := sha256.New()
81 rbytes, err := io.Copy(h, c)
82 if err != nil {
83 t.Error(err)
84 }
85
86 if rbytes != newtonLen {
87 t.Errorf("received %d bytes; expected %d", rbytes, newtonLen)
88 }
89
90 if res := hex.EncodeToString(h.Sum(nil)); res != newtonSHA256 {
91 t.Error("retrieved data hash did not match")
92 }
93
94 for err := range errc {
95 t.Error(err)
96 }
97 }
98
99 func TestSendfileParts(t *testing.T) {
100 ln, err := newLocalListener("tcp")
101 if err != nil {
102 t.Fatal(err)
103 }
104 defer ln.Close()
105
106 errc := make(chan error, 1)
107 go func(ln Listener) {
108 // Wait for a connection.
109 conn, err := ln.Accept()
110 if err != nil {
111 errc <- err
112 close(errc)
113 return
114 }
115
116 go func() {
117 defer close(errc)
118 defer conn.Close()
119
120 f, err := os.Open(newton)
121 if err != nil {
122 errc <- err
123 return
124 }
125 defer f.Close()
126
127 for i := 0; i < 3; i++ {
128 // Return file data using io.CopyN, which should use
129 // sendFile if available.
130 _, err = io.CopyN(conn, f, 3)
131 if err != nil {
132 errc <- err
133 return
134 }
135 }
136 }()
137 }(ln)
138
139 c, err := Dial("tcp", ln.Addr().String())
140 if err != nil {
141 t.Fatal(err)
142 }
143 defer c.Close()
144
145 buf := new(bytes.Buffer)
146 buf.ReadFrom(c)
147
148 if want, have := "Produced ", buf.String(); have != want {
149 t.Errorf("unexpected server reply %q, want %q", have, want)
150 }
151
152 for err := range errc {
153 t.Error(err)
154 }
155 }
156
157 func TestSendfileSeeked(t *testing.T) {
158 ln, err := newLocalListener("tcp")
159 if err != nil {
160 t.Fatal(err)
161 }
162 defer ln.Close()
163
164 const seekTo = 65 << 10
165 const sendSize = 10 << 10
166
167 errc := make(chan error, 1)
168 go func(ln Listener) {
169 // Wait for a connection.
170 conn, err := ln.Accept()
171 if err != nil {
172 errc <- err
173 close(errc)
174 return
175 }
176
177 go func() {
178 defer close(errc)
179 defer conn.Close()
180
181 f, err := os.Open(newton)
182 if err != nil {
183 errc <- err
184 return
185 }
186 defer f.Close()
187 if _, err := f.Seek(seekTo, os.SEEK_SET); err != nil {
188 errc <- err
189 return
190 }
191
192 _, err = io.CopyN(conn, f, sendSize)
193 if err != nil {
194 errc <- err
195 return
196 }
197 }()
198 }(ln)
199
200 c, err := Dial("tcp", ln.Addr().String())
201 if err != nil {
202 t.Fatal(err)
203 }
204 defer c.Close()
205
206 buf := new(bytes.Buffer)
207 buf.ReadFrom(c)
208
209 if buf.Len() != sendSize {
210 t.Errorf("Got %d bytes; want %d", buf.Len(), sendSize)
211 }
212
213 for err := range errc {
214 t.Error(err)
215 }
216 }
217
218 // Test that sendfile doesn't put a pipe into blocking mode.
219 func TestSendfilePipe(t *testing.T) {
220 switch runtime.GOOS {
221 case "nacl", "plan9", "windows":
222 // These systems don't support deadlines on pipes.
223 t.Skipf("skipping on %s", runtime.GOOS)
224 }
225
226 t.Parallel()
227
228 ln, err := newLocalListener("tcp")
229 if err != nil {
230 t.Fatal(err)
231 }
232 defer ln.Close()
233
234 r, w, err := os.Pipe()
235 if err != nil {
236 t.Fatal(err)
237 }
238 defer w.Close()
239 defer r.Close()
240
241 copied := make(chan bool)
242
243 var wg sync.WaitGroup
244 wg.Add(1)
245 go func() {
246 // Accept a connection and copy 1 byte from the read end of
247 // the pipe to the connection. This will call into sendfile.
248 defer wg.Done()
249 conn, err := ln.Accept()
250 if err != nil {
251 t.Error(err)
252 return
253 }
254 defer conn.Close()
255 _, err = io.CopyN(conn, r, 1)
256 if err != nil {
257 t.Error(err)
258 return
259 }
260 // Signal the main goroutine that we've copied the byte.
261 close(copied)
262 }()
263
264 wg.Add(1)
265 go func() {
266 // Write 1 byte to the write end of the pipe.
267 defer wg.Done()
268 _, err := w.Write([]byte{'a'})
269 if err != nil {
270 t.Error(err)
271 }
272 }()
273
274 wg.Add(1)
275 go func() {
276 // Connect to the server started two goroutines up and
277 // discard any data that it writes.
278 defer wg.Done()
279 conn, err := Dial("tcp", ln.Addr().String())
280 if err != nil {
281 t.Error(err)
282 return
283 }
284 defer conn.Close()
285 io.Copy(ioutil.Discard, conn)
286 }()
287
288 // Wait for the byte to be copied, meaning that sendfile has
289 // been called on the pipe.
290 <-copied
291
292 // Set a very short deadline on the read end of the pipe.
293 if err := r.SetDeadline(time.Now().Add(time.Microsecond)); err != nil {
294 t.Fatal(err)
295 }
296
297 wg.Add(1)
298 go func() {
299 // Wait for much longer than the deadline and write a byte
300 // to the pipe.
301 defer wg.Done()
302 time.Sleep(50 * time.Millisecond)
303 w.Write([]byte{'b'})
304 }()
305
306 // If this read does not time out, the pipe was incorrectly
307 // put into blocking mode.
308 _, err = r.Read(make([]byte, 1))
309 if err == nil {
310 t.Error("Read did not time out")
311 } else if !os.IsTimeout(err) {
312 t.Errorf("got error %v, expected a time out", err)
313 }
314
315 wg.Wait()
316 }