1
0
mirror of https://github.com/golang/go synced 2024-09-30 18:18:32 -06:00

net: convert many Close tests to use parallel subtests

Also set a deadline in TestCloseWrite so that we can more easily
determine which kind of connection is getting stuck on the
darwin-arm64-corellium builder (#34837).

Change-Id: I8ccacbf436e8e493fb2298a79b17e0af8fc6eb81
Reviewed-on: https://go-review.googlesource.com/c/go/+/227588
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Bryan C. Mills 2020-04-08 12:51:50 -04:00
parent 98b6c6aca6
commit c1f0edae04

View File

@ -23,50 +23,54 @@ func TestCloseRead(t *testing.T) {
case "plan9": case "plan9":
t.Skipf("not supported on %s", runtime.GOOS) t.Skipf("not supported on %s", runtime.GOOS)
} }
t.Parallel()
for _, network := range []string{"tcp", "unix", "unixpacket"} { for _, network := range []string{"tcp", "unix", "unixpacket"} {
if !testableNetwork(network) { network := network
t.Logf("skipping %s test", network) t.Run(network, func(t *testing.T) {
continue if !testableNetwork(network) {
} t.Skipf("network %s is not testable on the current platform", network)
ln, err := newLocalListener(network)
if err != nil {
t.Fatal(err)
}
switch network {
case "unix", "unixpacket":
defer os.Remove(ln.Addr().String())
}
defer ln.Close()
c, err := Dial(ln.Addr().Network(), ln.Addr().String())
if err != nil {
t.Fatal(err)
}
switch network {
case "unix", "unixpacket":
defer os.Remove(c.LocalAddr().String())
}
defer c.Close()
switch c := c.(type) {
case *TCPConn:
err = c.CloseRead()
case *UnixConn:
err = c.CloseRead()
}
if err != nil {
if perr := parseCloseError(err, true); perr != nil {
t.Error(perr)
} }
t.Fatal(err) t.Parallel()
}
var b [1]byte ln, err := newLocalListener(network)
n, err := c.Read(b[:]) if err != nil {
if n != 0 || err == nil { t.Fatal(err)
t.Fatalf("got (%d, %v); want (0, error)", n, err) }
} switch network {
case "unix", "unixpacket":
defer os.Remove(ln.Addr().String())
}
defer ln.Close()
c, err := Dial(ln.Addr().Network(), ln.Addr().String())
if err != nil {
t.Fatal(err)
}
switch network {
case "unix", "unixpacket":
defer os.Remove(c.LocalAddr().String())
}
defer c.Close()
switch c := c.(type) {
case *TCPConn:
err = c.CloseRead()
case *UnixConn:
err = c.CloseRead()
}
if err != nil {
if perr := parseCloseError(err, true); perr != nil {
t.Error(perr)
}
t.Fatal(err)
}
var b [1]byte
n, err := c.Read(b[:])
if n != 0 || err == nil {
t.Fatalf("got (%d, %v); want (0, error)", n, err)
}
})
} }
} }
@ -76,212 +80,240 @@ func TestCloseWrite(t *testing.T) {
t.Skipf("not supported on %s", runtime.GOOS) t.Skipf("not supported on %s", runtime.GOOS)
} }
handler := func(ls *localServer, ln Listener) { t.Parallel()
c, err := ln.Accept() deadline, _ := t.Deadline()
if err != nil { if !deadline.IsZero() {
t.Error(err) // Leave 10% headroom on the deadline to report errors and clean up.
return deadline = deadline.Add(-time.Until(deadline) / 10)
}
defer c.Close()
var b [1]byte
n, err := c.Read(b[:])
if n != 0 || err != io.EOF {
t.Errorf("got (%d, %v); want (0, io.EOF)", n, err)
return
}
switch c := c.(type) {
case *TCPConn:
err = c.CloseWrite()
case *UnixConn:
err = c.CloseWrite()
}
if err != nil {
if perr := parseCloseError(err, true); perr != nil {
t.Error(perr)
}
t.Error(err)
return
}
n, err = c.Write(b[:])
if err == nil {
t.Errorf("got (%d, %v); want (any, error)", n, err)
return
}
} }
for _, network := range []string{"tcp", "unix", "unixpacket"} { for _, network := range []string{"tcp", "unix", "unixpacket"} {
if !testableNetwork(network) { network := network
t.Logf("skipping %s test", network) t.Run(network, func(t *testing.T) {
continue if !testableNetwork(network) {
} t.Skipf("network %s is not testable on the current platform", network)
ls, err := newLocalServer(network)
if err != nil {
t.Fatal(err)
}
defer ls.teardown()
if err := ls.buildup(handler); err != nil {
t.Fatal(err)
}
c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
if err != nil {
t.Fatal(err)
}
switch network {
case "unix", "unixpacket":
defer os.Remove(c.LocalAddr().String())
}
defer c.Close()
switch c := c.(type) {
case *TCPConn:
err = c.CloseWrite()
case *UnixConn:
err = c.CloseWrite()
}
if err != nil {
if perr := parseCloseError(err, true); perr != nil {
t.Error(perr)
} }
t.Fatal(err) t.Parallel()
}
var b [1]byte handler := func(ls *localServer, ln Listener) {
n, err := c.Read(b[:]) c, err := ln.Accept()
if n != 0 || err != io.EOF { if err != nil {
t.Fatalf("got (%d, %v); want (0, io.EOF)", n, err) t.Error(err)
} return
n, err = c.Write(b[:]) }
if err == nil { if !deadline.IsZero() {
t.Fatalf("got (%d, %v); want (any, error)", n, err) c.SetDeadline(deadline)
} }
defer c.Close()
var b [1]byte
n, err := c.Read(b[:])
if n != 0 || err != io.EOF {
t.Errorf("got (%d, %v); want (0, io.EOF)", n, err)
return
}
switch c := c.(type) {
case *TCPConn:
err = c.CloseWrite()
case *UnixConn:
err = c.CloseWrite()
}
if err != nil {
if perr := parseCloseError(err, true); perr != nil {
t.Error(perr)
}
t.Error(err)
return
}
n, err = c.Write(b[:])
if err == nil {
t.Errorf("got (%d, %v); want (any, error)", n, err)
return
}
}
ls, err := newLocalServer(network)
if err != nil {
t.Fatal(err)
}
defer ls.teardown()
if err := ls.buildup(handler); err != nil {
t.Fatal(err)
}
c, err := Dial(ls.Listener.Addr().Network(), ls.Listener.Addr().String())
if err != nil {
t.Fatal(err)
}
if !deadline.IsZero() {
c.SetDeadline(deadline)
}
switch network {
case "unix", "unixpacket":
defer os.Remove(c.LocalAddr().String())
}
defer c.Close()
switch c := c.(type) {
case *TCPConn:
err = c.CloseWrite()
case *UnixConn:
err = c.CloseWrite()
}
if err != nil {
if perr := parseCloseError(err, true); perr != nil {
t.Error(perr)
}
t.Fatal(err)
}
var b [1]byte
n, err := c.Read(b[:])
if n != 0 || err != io.EOF {
t.Fatalf("got (%d, %v); want (0, io.EOF)", n, err)
}
n, err = c.Write(b[:])
if err == nil {
t.Fatalf("got (%d, %v); want (any, error)", n, err)
}
})
} }
} }
func TestConnClose(t *testing.T) { func TestConnClose(t *testing.T) {
t.Parallel()
for _, network := range []string{"tcp", "unix", "unixpacket"} { for _, network := range []string{"tcp", "unix", "unixpacket"} {
if !testableNetwork(network) { network := network
t.Logf("skipping %s test", network) t.Run(network, func(t *testing.T) {
continue if !testableNetwork(network) {
} t.Skipf("network %s is not testable on the current platform", network)
ln, err := newLocalListener(network)
if err != nil {
t.Fatal(err)
}
switch network {
case "unix", "unixpacket":
defer os.Remove(ln.Addr().String())
}
defer ln.Close()
c, err := Dial(ln.Addr().Network(), ln.Addr().String())
if err != nil {
t.Fatal(err)
}
switch network {
case "unix", "unixpacket":
defer os.Remove(c.LocalAddr().String())
}
defer c.Close()
if err := c.Close(); err != nil {
if perr := parseCloseError(err, false); perr != nil {
t.Error(perr)
} }
t.Fatal(err) t.Parallel()
}
var b [1]byte ln, err := newLocalListener(network)
n, err := c.Read(b[:]) if err != nil {
if n != 0 || err == nil { t.Fatal(err)
t.Fatalf("got (%d, %v); want (0, error)", n, err) }
} switch network {
case "unix", "unixpacket":
defer os.Remove(ln.Addr().String())
}
defer ln.Close()
c, err := Dial(ln.Addr().Network(), ln.Addr().String())
if err != nil {
t.Fatal(err)
}
switch network {
case "unix", "unixpacket":
defer os.Remove(c.LocalAddr().String())
}
defer c.Close()
if err := c.Close(); err != nil {
if perr := parseCloseError(err, false); perr != nil {
t.Error(perr)
}
t.Fatal(err)
}
var b [1]byte
n, err := c.Read(b[:])
if n != 0 || err == nil {
t.Fatalf("got (%d, %v); want (0, error)", n, err)
}
})
} }
} }
func TestListenerClose(t *testing.T) { func TestListenerClose(t *testing.T) {
t.Parallel()
for _, network := range []string{"tcp", "unix", "unixpacket"} { for _, network := range []string{"tcp", "unix", "unixpacket"} {
if !testableNetwork(network) { network := network
t.Logf("skipping %s test", network) t.Run(network, func(t *testing.T) {
continue if !testableNetwork(network) {
} t.Skipf("network %s is not testable on the current platform", network)
ln, err := newLocalListener(network)
if err != nil {
t.Fatal(err)
}
switch network {
case "unix", "unixpacket":
defer os.Remove(ln.Addr().String())
}
dst := ln.Addr().String()
if err := ln.Close(); err != nil {
if perr := parseCloseError(err, false); perr != nil {
t.Error(perr)
} }
t.Fatal(err) t.Parallel()
}
c, err := ln.Accept()
if err == nil {
c.Close()
t.Fatal("should fail")
}
if network == "tcp" { ln, err := newLocalListener(network)
// We will have two TCP FSMs inside the if err != nil {
// kernel here. There's no guarantee that a t.Fatal(err)
// signal comes from the far end FSM will be }
// delivered immediately to the near end FSM, switch network {
// especially on the platforms that allow case "unix", "unixpacket":
// multiple consumer threads to pull pending defer os.Remove(ln.Addr().String())
// established connections at the same time by }
// enabling SO_REUSEPORT option such as Linux,
// DragonFly BSD. So we need to give some time
// quantum to the kernel.
//
// Note that net.inet.tcp.reuseport_ext=1 by
// default on DragonFly BSD.
time.Sleep(time.Millisecond)
cc, err := Dial("tcp", dst) dst := ln.Addr().String()
if err := ln.Close(); err != nil {
if perr := parseCloseError(err, false); perr != nil {
t.Error(perr)
}
t.Fatal(err)
}
c, err := ln.Accept()
if err == nil { if err == nil {
t.Error("Dial to closed TCP listener succeeded.") c.Close()
cc.Close() t.Fatal("should fail")
} }
}
if network == "tcp" {
// We will have two TCP FSMs inside the
// kernel here. There's no guarantee that a
// signal comes from the far end FSM will be
// delivered immediately to the near end FSM,
// especially on the platforms that allow
// multiple consumer threads to pull pending
// established connections at the same time by
// enabling SO_REUSEPORT option such as Linux,
// DragonFly BSD. So we need to give some time
// quantum to the kernel.
//
// Note that net.inet.tcp.reuseport_ext=1 by
// default on DragonFly BSD.
time.Sleep(time.Millisecond)
cc, err := Dial("tcp", dst)
if err == nil {
t.Error("Dial to closed TCP listener succeeded.")
cc.Close()
}
}
})
} }
} }
func TestPacketConnClose(t *testing.T) { func TestPacketConnClose(t *testing.T) {
t.Parallel()
for _, network := range []string{"udp", "unixgram"} { for _, network := range []string{"udp", "unixgram"} {
if !testableNetwork(network) { network := network
t.Logf("skipping %s test", network) t.Run(network, func(t *testing.T) {
continue if !testableNetwork(network) {
} t.Skipf("network %s is not testable on the current platform", network)
c, err := newLocalPacketListener(network)
if err != nil {
t.Fatal(err)
}
switch network {
case "unixgram":
defer os.Remove(c.LocalAddr().String())
}
defer c.Close()
if err := c.Close(); err != nil {
if perr := parseCloseError(err, false); perr != nil {
t.Error(perr)
} }
t.Fatal(err) t.Parallel()
}
var b [1]byte c, err := newLocalPacketListener(network)
n, _, err := c.ReadFrom(b[:]) if err != nil {
if n != 0 || err == nil { t.Fatal(err)
t.Fatalf("got (%d, %v); want (0, error)", n, err) }
} switch network {
case "unixgram":
defer os.Remove(c.LocalAddr().String())
}
defer c.Close()
if err := c.Close(); err != nil {
if perr := parseCloseError(err, false); perr != nil {
t.Error(perr)
}
t.Fatal(err)
}
var b [1]byte
n, _, err := c.ReadFrom(b[:])
if n != 0 || err == nil {
t.Fatalf("got (%d, %v); want (0, error)", n, err)
}
})
} }
} }
@ -366,56 +398,60 @@ func TestAcceptIgnoreAbortedConnRequest(t *testing.T) {
} }
func TestZeroByteRead(t *testing.T) { func TestZeroByteRead(t *testing.T) {
t.Parallel()
for _, network := range []string{"tcp", "unix", "unixpacket"} { for _, network := range []string{"tcp", "unix", "unixpacket"} {
if !testableNetwork(network) { network := network
t.Logf("skipping %s test", network) t.Run(network, func(t *testing.T) {
continue if !testableNetwork(network) {
} t.Skipf("network %s is not testable on the current platform", network)
ln, err := newLocalListener(network)
if err != nil {
t.Fatal(err)
}
connc := make(chan Conn, 1)
go func() {
defer ln.Close()
c, err := ln.Accept()
if err != nil {
t.Error(err)
} }
connc <- c // might be nil t.Parallel()
}()
c, err := Dial(network, ln.Addr().String())
if err != nil {
t.Fatal(err)
}
defer c.Close()
sc := <-connc
if sc == nil {
continue
}
defer sc.Close()
if runtime.GOOS == "windows" { ln, err := newLocalListener(network)
// A zero byte read on Windows caused a wait for readability first. if err != nil {
// Rather than change that behavior, satisfy it in this test. t.Fatal(err)
// See Issue 15735. }
go io.WriteString(sc, "a") connc := make(chan Conn, 1)
} go func() {
defer ln.Close()
c, err := ln.Accept()
if err != nil {
t.Error(err)
}
connc <- c // might be nil
}()
c, err := Dial(network, ln.Addr().String())
if err != nil {
t.Fatal(err)
}
defer c.Close()
sc := <-connc
if sc == nil {
return
}
defer sc.Close()
n, err := c.Read(nil) if runtime.GOOS == "windows" {
if n != 0 || err != nil { // A zero byte read on Windows caused a wait for readability first.
t.Errorf("%s: zero byte client read = %v, %v; want 0, nil", network, n, err) // Rather than change that behavior, satisfy it in this test.
} // See Issue 15735.
go io.WriteString(sc, "a")
}
if runtime.GOOS == "windows" { n, err := c.Read(nil)
// Same as comment above. if n != 0 || err != nil {
go io.WriteString(c, "a") t.Errorf("%s: zero byte client read = %v, %v; want 0, nil", network, n, err)
} }
n, err = sc.Read(nil)
if n != 0 || err != nil { if runtime.GOOS == "windows" {
t.Errorf("%s: zero byte server read = %v, %v; want 0, nil", network, n, err) // Same as comment above.
} go io.WriteString(c, "a")
}
n, err = sc.Read(nil)
if n != 0 || err != nil {
t.Errorf("%s: zero byte server read = %v, %v; want 0, nil", network, n, err)
}
})
} }
} }