package tls
import (
+ "fmt"
"io"
"net"
"strings"
// (non-zero, nil) when a Close (alertCloseNotify) is sitting right
// behind the application data in the buffer.
func TestConnReadNonzeroAndEOF(t *testing.T) {
+ // This test is racy: it assumes that after a write to a
+ // localhost TCP connection, the peer TCP connection can
+ // immediately read it. Because it's racy, we skip this test
+ // in short mode, and then retry it several times with an
+ // increasing sleep in between our final write (via srv.Close
+ // below) and the following read.
+ if testing.Short() {
+ t.Skip("skipping in short mode")
+ }
+ var err error
+ for delay := time.Millisecond; delay <= 64*time.Millisecond; delay *= 2 {
+ if err = testConnReadNonzeroAndEOF(t, delay); err == nil {
+ return
+ }
+ }
+ t.Error(err)
+}
+
+func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
ln := newLocalListener(t)
defer ln.Close()
srvCh := make(chan *Conn, 1)
+ var serr error
go func() {
sconn, err := ln.Accept()
if err != nil {
- t.Error(err)
+ serr = err
srvCh <- nil
return
}
serverConfig := *testConfig
srv := Server(sconn, &serverConfig)
if err := srv.Handshake(); err != nil {
- t.Error("handshake: %v", err)
+ serr = fmt.Errorf("handshake: %v", err)
srvCh <- nil
return
}
srv := <-srvCh
if srv == nil {
- return
+ return serr
}
buf := make([]byte, 6)
srv.Write([]byte("foobar"))
n, err := conn.Read(buf)
if n != 6 || err != nil || string(buf) != "foobar" {
- t.Fatalf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf)
+ return fmt.Errorf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf)
}
srv.Write([]byte("abcdef"))
srv.Close()
+ time.Sleep(delay)
n, err = conn.Read(buf)
if n != 6 || string(buf) != "abcdef" {
- t.Fatalf("Read = %d, buf= %q; want 6, abcdef", n, buf)
+ return fmt.Errorf("Read = %d, buf= %q; want 6, abcdef", n, buf)
}
if err != io.EOF {
- t.Errorf("Second Read error = %v; want io.EOF", err)
+ return fmt.Errorf("Second Read error = %v; want io.EOF", err)
}
+ return nil
}