diff options
Diffstat (limited to 'libgo/go/net/sendfile_test.go')
-rw-r--r-- | libgo/go/net/sendfile_test.go | 126 |
1 files changed, 115 insertions, 11 deletions
diff --git a/libgo/go/net/sendfile_test.go b/libgo/go/net/sendfile_test.go index 3b982774b02..911e6139c57 100644 --- a/libgo/go/net/sendfile_test.go +++ b/libgo/go/net/sendfile_test.go @@ -12,14 +12,18 @@ import ( "encoding/hex" "fmt" "io" + "io/ioutil" "os" + "runtime" + "sync" "testing" + "time" ) const ( - twain = "testdata/Mark.Twain-Tom.Sawyer.txt" - twainLen = 387851 - twainSHA256 = "461eb7cb2d57d293fc680c836464c9125e4382be3596f7d415093ae9db8fcb0e" + newton = "../testdata/Isaac.Newton-Opticks.txt" + newtonLen = 567198 + newtonSHA256 = "d4a9ac22462b35e7821a4f2706c211093da678620a8f9997989ee7cf8d507bbd" ) func TestSendfile(t *testing.T) { @@ -43,7 +47,7 @@ func TestSendfile(t *testing.T) { defer close(errc) defer conn.Close() - f, err := os.Open(twain) + f, err := os.Open(newton) if err != nil { errc <- err return @@ -58,8 +62,8 @@ func TestSendfile(t *testing.T) { return } - if sbytes != twainLen { - errc <- fmt.Errorf("sent %d bytes; expected %d", sbytes, twainLen) + if sbytes != newtonLen { + errc <- fmt.Errorf("sent %d bytes; expected %d", sbytes, newtonLen) return } }() @@ -79,11 +83,11 @@ func TestSendfile(t *testing.T) { t.Error(err) } - if rbytes != twainLen { - t.Errorf("received %d bytes; expected %d", rbytes, twainLen) + if rbytes != newtonLen { + t.Errorf("received %d bytes; expected %d", rbytes, newtonLen) } - if res := hex.EncodeToString(h.Sum(nil)); res != twainSHA256 { + if res := hex.EncodeToString(h.Sum(nil)); res != newtonSHA256 { t.Error("retrieved data hash did not match") } @@ -113,7 +117,7 @@ func TestSendfileParts(t *testing.T) { defer close(errc) defer conn.Close() - f, err := os.Open(twain) + f, err := os.Open(newton) if err != nil { errc <- err return @@ -174,7 +178,7 @@ func TestSendfileSeeked(t *testing.T) { defer close(errc) defer conn.Close() - f, err := os.Open(twain) + f, err := os.Open(newton) if err != nil { errc <- err return @@ -210,3 +214,103 @@ func TestSendfileSeeked(t *testing.T) { t.Error(err) } } + +// Test that sendfile doesn't put a pipe into blocking mode. +func TestSendfilePipe(t *testing.T) { + switch runtime.GOOS { + case "nacl", "plan9", "windows": + // These systems don't support deadlines on pipes. + t.Skipf("skipping on %s", runtime.GOOS) + } + + t.Parallel() + + ln, err := newLocalListener("tcp") + if err != nil { + t.Fatal(err) + } + defer ln.Close() + + r, w, err := os.Pipe() + if err != nil { + t.Fatal(err) + } + defer w.Close() + defer r.Close() + + copied := make(chan bool) + + var wg sync.WaitGroup + wg.Add(1) + go func() { + // Accept a connection and copy 1 byte from the read end of + // the pipe to the connection. This will call into sendfile. + defer wg.Done() + conn, err := ln.Accept() + if err != nil { + t.Error(err) + return + } + defer conn.Close() + _, err = io.CopyN(conn, r, 1) + if err != nil { + t.Error(err) + return + } + // Signal the main goroutine that we've copied the byte. + close(copied) + }() + + wg.Add(1) + go func() { + // Write 1 byte to the write end of the pipe. + defer wg.Done() + _, err := w.Write([]byte{'a'}) + if err != nil { + t.Error(err) + } + }() + + wg.Add(1) + go func() { + // Connect to the server started two goroutines up and + // discard any data that it writes. + defer wg.Done() + conn, err := Dial("tcp", ln.Addr().String()) + if err != nil { + t.Error(err) + return + } + defer conn.Close() + io.Copy(ioutil.Discard, conn) + }() + + // Wait for the byte to be copied, meaning that sendfile has + // been called on the pipe. + <-copied + + // Set a very short deadline on the read end of the pipe. + if err := r.SetDeadline(time.Now().Add(time.Microsecond)); err != nil { + t.Fatal(err) + } + + wg.Add(1) + go func() { + // Wait for much longer than the deadline and write a byte + // to the pipe. + defer wg.Done() + time.Sleep(50 * time.Millisecond) + w.Write([]byte{'b'}) + }() + + // If this read does not time out, the pipe was incorrectly + // put into blocking mode. + _, err = r.Read(make([]byte, 1)) + if err == nil { + t.Error("Read did not time out") + } else if !os.IsTimeout(err) { + t.Errorf("got error %v, expected a time out", err) + } + + wg.Wait() +} |