2016-04-08 15:59:04 -07:00
|
|
|
// Copyright 2016 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
2018-03-04 12:18:32 +01:00
|
|
|
// +build !js
|
|
|
|
|
|
2016-04-08 15:59:04 -07:00
|
|
|
package net
|
|
|
|
|
|
|
|
|
|
import (
|
2018-06-11 11:03:25 +10:00
|
|
|
"bytes"
|
2016-04-08 15:59:04 -07:00
|
|
|
"crypto/sha256"
|
|
|
|
|
"encoding/hex"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"os"
|
|
|
|
|
"testing"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
2018-10-01 15:07:51 +00:00
|
|
|
newton = "../testdata/Isaac.Newton-Opticks.txt"
|
2018-09-14 17:07:56 -04:00
|
|
|
newtonLen = 567198
|
|
|
|
|
newtonSHA256 = "d4a9ac22462b35e7821a4f2706c211093da678620a8f9997989ee7cf8d507bbd"
|
2016-04-08 15:59:04 -07:00
|
|
|
)
|
|
|
|
|
|
2016-04-12 21:51:19 +00:00
|
|
|
func TestSendfile(t *testing.T) {
|
2016-04-08 15:59:04 -07:00
|
|
|
ln, err := newLocalListener("tcp")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer ln.Close()
|
|
|
|
|
|
|
|
|
|
errc := make(chan error, 1)
|
|
|
|
|
go func(ln Listener) {
|
|
|
|
|
// Wait for a connection.
|
|
|
|
|
conn, err := ln.Accept()
|
|
|
|
|
if err != nil {
|
|
|
|
|
errc <- err
|
|
|
|
|
close(errc)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
|
defer close(errc)
|
|
|
|
|
defer conn.Close()
|
|
|
|
|
|
2018-09-14 17:07:56 -04:00
|
|
|
f, err := os.Open(newton)
|
2016-04-08 15:59:04 -07:00
|
|
|
if err != nil {
|
|
|
|
|
errc <- err
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
|
|
// Return file data using io.Copy, which should use
|
|
|
|
|
// sendFile if available.
|
|
|
|
|
sbytes, err := io.Copy(conn, f)
|
|
|
|
|
if err != nil {
|
|
|
|
|
errc <- err
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-14 17:07:56 -04:00
|
|
|
if sbytes != newtonLen {
|
|
|
|
|
errc <- fmt.Errorf("sent %d bytes; expected %d", sbytes, newtonLen)
|
2016-04-08 15:59:04 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
}(ln)
|
|
|
|
|
|
|
|
|
|
// Connect to listener to retrieve file and verify digest matches
|
|
|
|
|
// expected.
|
|
|
|
|
c, err := Dial("tcp", ln.Addr().String())
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer c.Close()
|
|
|
|
|
|
|
|
|
|
h := sha256.New()
|
|
|
|
|
rbytes, err := io.Copy(h, c)
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Error(err)
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-14 17:07:56 -04:00
|
|
|
if rbytes != newtonLen {
|
|
|
|
|
t.Errorf("received %d bytes; expected %d", rbytes, newtonLen)
|
2016-04-08 15:59:04 -07:00
|
|
|
}
|
|
|
|
|
|
2018-09-14 17:07:56 -04:00
|
|
|
if res := hex.EncodeToString(h.Sum(nil)); res != newtonSHA256 {
|
2016-04-08 15:59:04 -07:00
|
|
|
t.Error("retrieved data hash did not match")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for err := range errc {
|
|
|
|
|
t.Error(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-11 11:03:25 +10:00
|
|
|
|
|
|
|
|
func TestSendfileParts(t *testing.T) {
|
|
|
|
|
ln, err := newLocalListener("tcp")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer ln.Close()
|
|
|
|
|
|
|
|
|
|
errc := make(chan error, 1)
|
|
|
|
|
go func(ln Listener) {
|
|
|
|
|
// Wait for a connection.
|
|
|
|
|
conn, err := ln.Accept()
|
|
|
|
|
if err != nil {
|
|
|
|
|
errc <- err
|
|
|
|
|
close(errc)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
|
defer close(errc)
|
|
|
|
|
defer conn.Close()
|
|
|
|
|
|
2018-09-14 17:07:56 -04:00
|
|
|
f, err := os.Open(newton)
|
2018-06-11 11:03:25 +10:00
|
|
|
if err != nil {
|
|
|
|
|
errc <- err
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
|
|
for i := 0; i < 3; i++ {
|
|
|
|
|
// Return file data using io.CopyN, which should use
|
|
|
|
|
// sendFile if available.
|
|
|
|
|
_, err = io.CopyN(conn, f, 3)
|
|
|
|
|
if err != nil {
|
|
|
|
|
errc <- err
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
}(ln)
|
|
|
|
|
|
|
|
|
|
c, err := Dial("tcp", ln.Addr().String())
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer c.Close()
|
|
|
|
|
|
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
|
buf.ReadFrom(c)
|
|
|
|
|
|
|
|
|
|
if want, have := "Produced ", buf.String(); have != want {
|
|
|
|
|
t.Errorf("unexpected server reply %q, want %q", have, want)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for err := range errc {
|
|
|
|
|
t.Error(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-08-22 20:31:37 +00:00
|
|
|
|
|
|
|
|
func TestSendfileSeeked(t *testing.T) {
|
|
|
|
|
ln, err := newLocalListener("tcp")
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer ln.Close()
|
|
|
|
|
|
|
|
|
|
const seekTo = 65 << 10
|
|
|
|
|
const sendSize = 10 << 10
|
|
|
|
|
|
|
|
|
|
errc := make(chan error, 1)
|
|
|
|
|
go func(ln Listener) {
|
|
|
|
|
// Wait for a connection.
|
|
|
|
|
conn, err := ln.Accept()
|
|
|
|
|
if err != nil {
|
|
|
|
|
errc <- err
|
|
|
|
|
close(errc)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
|
defer close(errc)
|
|
|
|
|
defer conn.Close()
|
|
|
|
|
|
2018-09-14 17:07:56 -04:00
|
|
|
f, err := os.Open(newton)
|
2018-08-22 20:31:37 +00:00
|
|
|
if err != nil {
|
|
|
|
|
errc <- err
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
defer f.Close()
|
|
|
|
|
if _, err := f.Seek(seekTo, os.SEEK_SET); err != nil {
|
|
|
|
|
errc <- err
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err = io.CopyN(conn, f, sendSize)
|
|
|
|
|
if err != nil {
|
|
|
|
|
errc <- err
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
}(ln)
|
|
|
|
|
|
|
|
|
|
c, err := Dial("tcp", ln.Addr().String())
|
|
|
|
|
if err != nil {
|
|
|
|
|
t.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
defer c.Close()
|
|
|
|
|
|
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
|
buf.ReadFrom(c)
|
|
|
|
|
|
|
|
|
|
if buf.Len() != sendSize {
|
|
|
|
|
t.Errorf("Got %d bytes; want %d", buf.Len(), sendSize)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for err := range errc {
|
|
|
|
|
t.Error(err)
|
|
|
|
|
}
|
|
|
|
|
}
|