From 53431b940d42f9c493908f67b3d27734be8e70e2 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 2 Apr 2014 14:31:57 -0700 Subject: [PATCH] crypto/tls: deflake TestConnReadNonzeroAndEOF Fixes #7683 LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/83080048 --- tls_test.go | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/tls_test.go b/tls_test.go index 65a243d..f8c94ff 100644 --- a/tls_test.go +++ b/tls_test.go @@ -5,6 +5,7 @@ package tls import ( + "fmt" "io" "net" "strings" @@ -161,21 +162,41 @@ func TestDialTimeout(t *testing.T) { // (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 } @@ -191,7 +212,7 @@ func TestConnReadNonzeroAndEOF(t *testing.T) { srv := <-srvCh if srv == nil { - return + return serr } buf := make([]byte, 6) @@ -199,16 +220,18 @@ func TestConnReadNonzeroAndEOF(t *testing.T) { 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 }