Source file
src/net/sendfile_test.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "bytes"
11 "crypto/sha256"
12 "encoding/hex"
13 "errors"
14 "fmt"
15 "io"
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 := newLocalListener(t, "tcp")
31 defer ln.Close()
32
33 errc := make(chan error, 1)
34 go func(ln Listener) {
35
36 conn, err := ln.Accept()
37 if err != nil {
38 errc <- err
39 close(errc)
40 return
41 }
42
43 go func() {
44 defer close(errc)
45 defer conn.Close()
46
47 f, err := os.Open(newton)
48 if err != nil {
49 errc <- err
50 return
51 }
52 defer f.Close()
53
54
55
56 sbytes, err := io.Copy(conn, f)
57 if err != nil {
58 errc <- err
59 return
60 }
61
62 if sbytes != newtonLen {
63 errc <- fmt.Errorf("sent %d bytes; expected %d", sbytes, newtonLen)
64 return
65 }
66 }()
67 }(ln)
68
69
70
71 c, err := Dial("tcp", ln.Addr().String())
72 if err != nil {
73 t.Fatal(err)
74 }
75 defer c.Close()
76
77 h := sha256.New()
78 rbytes, err := io.Copy(h, c)
79 if err != nil {
80 t.Error(err)
81 }
82
83 if rbytes != newtonLen {
84 t.Errorf("received %d bytes; expected %d", rbytes, newtonLen)
85 }
86
87 if res := hex.EncodeToString(h.Sum(nil)); res != newtonSHA256 {
88 t.Error("retrieved data hash did not match")
89 }
90
91 for err := range errc {
92 t.Error(err)
93 }
94 }
95
96 func TestSendfileParts(t *testing.T) {
97 ln := newLocalListener(t, "tcp")
98 defer ln.Close()
99
100 errc := make(chan error, 1)
101 go func(ln Listener) {
102
103 conn, err := ln.Accept()
104 if err != nil {
105 errc <- err
106 close(errc)
107 return
108 }
109
110 go func() {
111 defer close(errc)
112 defer conn.Close()
113
114 f, err := os.Open(newton)
115 if err != nil {
116 errc <- err
117 return
118 }
119 defer f.Close()
120
121 for i := 0; i < 3; i++ {
122
123
124 _, err = io.CopyN(conn, f, 3)
125 if err != nil {
126 errc <- err
127 return
128 }
129 }
130 }()
131 }(ln)
132
133 c, err := Dial("tcp", ln.Addr().String())
134 if err != nil {
135 t.Fatal(err)
136 }
137 defer c.Close()
138
139 buf := new(bytes.Buffer)
140 buf.ReadFrom(c)
141
142 if want, have := "Produced ", buf.String(); have != want {
143 t.Errorf("unexpected server reply %q, want %q", have, want)
144 }
145
146 for err := range errc {
147 t.Error(err)
148 }
149 }
150
151 func TestSendfileSeeked(t *testing.T) {
152 ln := newLocalListener(t, "tcp")
153 defer ln.Close()
154
155 const seekTo = 65 << 10
156 const sendSize = 10 << 10
157
158 errc := make(chan error, 1)
159 go func(ln Listener) {
160
161 conn, err := ln.Accept()
162 if err != nil {
163 errc <- err
164 close(errc)
165 return
166 }
167
168 go func() {
169 defer close(errc)
170 defer conn.Close()
171
172 f, err := os.Open(newton)
173 if err != nil {
174 errc <- err
175 return
176 }
177 defer f.Close()
178 if _, err := f.Seek(seekTo, os.SEEK_SET); err != nil {
179 errc <- err
180 return
181 }
182
183 _, err = io.CopyN(conn, f, sendSize)
184 if err != nil {
185 errc <- err
186 return
187 }
188 }()
189 }(ln)
190
191 c, err := Dial("tcp", ln.Addr().String())
192 if err != nil {
193 t.Fatal(err)
194 }
195 defer c.Close()
196
197 buf := new(bytes.Buffer)
198 buf.ReadFrom(c)
199
200 if buf.Len() != sendSize {
201 t.Errorf("Got %d bytes; want %d", buf.Len(), sendSize)
202 }
203
204 for err := range errc {
205 t.Error(err)
206 }
207 }
208
209
210 func TestSendfilePipe(t *testing.T) {
211 switch runtime.GOOS {
212 case "plan9", "windows":
213
214 t.Skipf("skipping on %s", runtime.GOOS)
215 }
216
217 t.Parallel()
218
219 ln := newLocalListener(t, "tcp")
220 defer ln.Close()
221
222 r, w, err := os.Pipe()
223 if err != nil {
224 t.Fatal(err)
225 }
226 defer w.Close()
227 defer r.Close()
228
229 copied := make(chan bool)
230
231 var wg sync.WaitGroup
232 wg.Add(1)
233 go func() {
234
235
236 defer wg.Done()
237 conn, err := ln.Accept()
238 if err != nil {
239 t.Error(err)
240 return
241 }
242 defer conn.Close()
243 _, err = io.CopyN(conn, r, 1)
244 if err != nil {
245 t.Error(err)
246 return
247 }
248
249 close(copied)
250 }()
251
252 wg.Add(1)
253 go func() {
254
255 defer wg.Done()
256 _, err := w.Write([]byte{'a'})
257 if err != nil {
258 t.Error(err)
259 }
260 }()
261
262 wg.Add(1)
263 go func() {
264
265
266 defer wg.Done()
267 conn, err := Dial("tcp", ln.Addr().String())
268 if err != nil {
269 t.Error(err)
270 return
271 }
272 defer conn.Close()
273 io.Copy(io.Discard, conn)
274 }()
275
276
277
278 <-copied
279
280
281 if err := r.SetDeadline(time.Now().Add(time.Microsecond)); err != nil {
282 t.Fatal(err)
283 }
284
285 wg.Add(1)
286 go func() {
287
288
289 defer wg.Done()
290 time.Sleep(50 * time.Millisecond)
291 w.Write([]byte{'b'})
292 }()
293
294
295
296 _, err = r.Read(make([]byte, 1))
297 if err == nil {
298 t.Error("Read did not time out")
299 } else if !os.IsTimeout(err) {
300 t.Errorf("got error %v, expected a time out", err)
301 }
302
303 wg.Wait()
304 }
305
306
307 func TestSendfileOnWriteTimeoutExceeded(t *testing.T) {
308 ln := newLocalListener(t, "tcp")
309 defer ln.Close()
310
311 errc := make(chan error, 1)
312 go func(ln Listener) (retErr error) {
313 defer func() {
314 errc <- retErr
315 close(errc)
316 }()
317
318 conn, err := ln.Accept()
319 if err != nil {
320 return err
321 }
322 defer conn.Close()
323
324
325
326 if err := conn.SetWriteDeadline(time.Now().Add(-1 * time.Hour)); err != nil {
327 return err
328 }
329
330 f, err := os.Open(newton)
331 if err != nil {
332 return err
333 }
334 defer f.Close()
335
336 _, err = io.Copy(conn, f)
337 if errors.Is(err, os.ErrDeadlineExceeded) {
338 return nil
339 }
340
341 if err == nil {
342 err = fmt.Errorf("expected ErrDeadlineExceeded, but got nil")
343 }
344 return err
345 }(ln)
346
347 conn, err := Dial("tcp", ln.Addr().String())
348 if err != nil {
349 t.Fatal(err)
350 }
351 defer conn.Close()
352
353 n, err := io.Copy(io.Discard, conn)
354 if err != nil {
355 t.Fatalf("expected nil error, but got %v", err)
356 }
357 if n != 0 {
358 t.Fatalf("expected receive zero, but got %d byte(s)", n)
359 }
360
361 if err := <-errc; err != nil {
362 t.Fatal(err)
363 }
364 }
365
View as plain text