1
0
mirror of https://github.com/golang/go synced 2024-10-05 11:41:22 -06:00
go/src/net/net_windows_test.go
Alex Brainman 71bf182028 net: relax error checking in TestAcceptIgnoreSomeErrors
TestAcceptIgnoreSomeErrors was created to test that network
accept function ignores some errors. But conditions created
by the test also affects network reads. Change the test to
ignore these read errors when acceptable.

Fixes #10785

Change-Id: I3da85cb55bd3e78c1980ad949e53e82391f9b41e
Reviewed-on: https://go-review.googlesource.com/9942
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2015-05-12 04:02:25 +00:00

166 lines
3.6 KiB
Go

// Copyright 2014 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.
package net
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
"syscall"
"testing"
"time"
)
func toErrno(err error) (syscall.Errno, bool) {
operr, ok := err.(*OpError)
if !ok {
return 0, false
}
syserr, ok := operr.Err.(*os.SyscallError)
if !ok {
return 0, false
}
errno, ok := syserr.Err.(syscall.Errno)
if !ok {
return 0, false
}
return errno, true
}
// TestAcceptIgnoreSomeErrors tests that windows TCPListener.AcceptTCP
// handles broken connections. It verifies that broken connections do
// not affect future connections.
func TestAcceptIgnoreSomeErrors(t *testing.T) {
recv := func(ln Listener, ignoreSomeReadErrors bool) (string, error) {
c, err := ln.Accept()
if err != nil {
// Display windows errno in error message.
errno, ok := toErrno(err)
if !ok {
return "", err
}
return "", fmt.Errorf("%v (windows errno=%d)", err, errno)
}
defer c.Close()
b := make([]byte, 100)
n, err := c.Read(b)
if err == nil || err == io.EOF {
return string(b[:n]), nil
}
errno, ok := toErrno(err)
if ok && ignoreSomeReadErrors && (errno == syscall.ERROR_NETNAME_DELETED || errno == syscall.WSAECONNRESET) {
return "", nil
}
return "", err
}
send := func(addr string, data string) error {
c, err := Dial("tcp", addr)
if err != nil {
return err
}
defer c.Close()
b := []byte(data)
n, err := c.Write(b)
if err != nil {
return err
}
if n != len(b) {
return fmt.Errorf(`Only %d chars of string "%s" sent`, n, data)
}
return nil
}
if envaddr := os.Getenv("GOTEST_DIAL_ADDR"); envaddr != "" {
// In child process.
c, err := Dial("tcp", envaddr)
if err != nil {
t.Fatal(err)
}
fmt.Printf("sleeping\n")
time.Sleep(time.Minute) // process will be killed here
c.Close()
}
ln, err := Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
defer ln.Close()
// Start child process that connects to our listener.
cmd := exec.Command(os.Args[0], "-test.run=TestAcceptIgnoreSomeErrors")
cmd.Env = append(os.Environ(), "GOTEST_DIAL_ADDR="+ln.Addr().String())
stdout, err := cmd.StdoutPipe()
if err != nil {
t.Fatalf("cmd.StdoutPipe failed: %v", err)
}
err = cmd.Start()
if err != nil {
t.Fatalf("cmd.Start failed: %v\n", err)
}
outReader := bufio.NewReader(stdout)
for {
s, err := outReader.ReadString('\n')
if err != nil {
t.Fatalf("reading stdout failed: %v", err)
}
if s == "sleeping\n" {
break
}
}
defer cmd.Wait() // ignore error - we know it is getting killed
const alittle = 100 * time.Millisecond
time.Sleep(alittle)
cmd.Process.Kill() // the only way to trigger the errors
time.Sleep(alittle)
// Send second connection data (with delay in a separate goroutine).
result := make(chan error)
go func() {
time.Sleep(alittle)
err := send(ln.Addr().String(), "abc")
if err != nil {
result <- err
}
result <- nil
}()
defer func() {
err := <-result
if err != nil {
t.Fatalf("send failed: %v", err)
}
}()
// Receive first or second connection.
s, err := recv(ln, true)
if err != nil {
t.Fatalf("recv failed: %v", err)
}
switch s {
case "":
// First connection data is received, let's get second connection data.
case "abc":
// First connection is lost forever, but that is ok.
return
default:
t.Fatalf(`"%s" received from recv, but "" or "abc" expected`, s)
}
// Get second connection data.
s, err = recv(ln, false)
if err != nil {
t.Fatalf("recv failed: %v", err)
}
if s != "abc" {
t.Fatalf(`"%s" received from recv, but "abc" expected`, s)
}
}