Home | History | Annotate | Download | only in net
      1 // Copyright 2015 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package net
      6 
      7 import (
      8 	"context"
      9 	"fmt"
     10 	"internal/poll"
     11 	"io"
     12 	"io/ioutil"
     13 	"net/internal/socktest"
     14 	"os"
     15 	"runtime"
     16 	"strings"
     17 	"testing"
     18 	"time"
     19 )
     20 
     21 func (e *OpError) isValid() error {
     22 	if e.Op == "" {
     23 		return fmt.Errorf("OpError.Op is empty: %v", e)
     24 	}
     25 	if e.Net == "" {
     26 		return fmt.Errorf("OpError.Net is empty: %v", e)
     27 	}
     28 	for _, addr := range []Addr{e.Source, e.Addr} {
     29 		switch addr := addr.(type) {
     30 		case nil:
     31 		case *TCPAddr:
     32 			if addr == nil {
     33 				return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
     34 			}
     35 		case *UDPAddr:
     36 			if addr == nil {
     37 				return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
     38 			}
     39 		case *IPAddr:
     40 			if addr == nil {
     41 				return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
     42 			}
     43 		case *IPNet:
     44 			if addr == nil {
     45 				return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
     46 			}
     47 		case *UnixAddr:
     48 			if addr == nil {
     49 				return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
     50 			}
     51 		case *pipeAddr:
     52 			if addr == nil {
     53 				return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
     54 			}
     55 		case fileAddr:
     56 			if addr == "" {
     57 				return fmt.Errorf("OpError.Source or Addr is empty: %#v, %v", addr, e)
     58 			}
     59 		default:
     60 			return fmt.Errorf("OpError.Source or Addr is unknown type: %T, %v", addr, e)
     61 		}
     62 	}
     63 	if e.Err == nil {
     64 		return fmt.Errorf("OpError.Err is empty: %v", e)
     65 	}
     66 	return nil
     67 }
     68 
     69 // parseDialError parses nestedErr and reports whether it is a valid
     70 // error value from Dial, Listen functions.
     71 // It returns nil when nestedErr is valid.
     72 func parseDialError(nestedErr error) error {
     73 	if nestedErr == nil {
     74 		return nil
     75 	}
     76 
     77 	switch err := nestedErr.(type) {
     78 	case *OpError:
     79 		if err := err.isValid(); err != nil {
     80 			return err
     81 		}
     82 		nestedErr = err.Err
     83 		goto second
     84 	}
     85 	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
     86 
     87 second:
     88 	if isPlatformError(nestedErr) {
     89 		return nil
     90 	}
     91 	switch err := nestedErr.(type) {
     92 	case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *poll.TimeoutError, UnknownNetworkError:
     93 		return nil
     94 	case *os.SyscallError:
     95 		nestedErr = err.Err
     96 		goto third
     97 	case *os.PathError: // for Plan 9
     98 		nestedErr = err.Err
     99 		goto third
    100 	}
    101 	switch nestedErr {
    102 	case errCanceled, poll.ErrNetClosing, errMissingAddress, errNoSuitableAddress,
    103 		context.DeadlineExceeded, context.Canceled:
    104 		return nil
    105 	}
    106 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
    107 
    108 third:
    109 	if isPlatformError(nestedErr) {
    110 		return nil
    111 	}
    112 	return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
    113 }
    114 
    115 var dialErrorTests = []struct {
    116 	network, address string
    117 }{
    118 	{"foo", ""},
    119 	{"bar", "baz"},
    120 	{"datakit", "mh/astro/r70"},
    121 	{"tcp", ""},
    122 	{"tcp", "127.0.0.1:"},
    123 	{"tcp", "no-such-name:80"},
    124 	{"tcp", "mh/astro/r70:http"},
    125 
    126 	{"tcp", JoinHostPort("127.0.0.1", "-1")},
    127 	{"tcp", JoinHostPort("127.0.0.1", "123456789")},
    128 	{"udp", JoinHostPort("127.0.0.1", "-1")},
    129 	{"udp", JoinHostPort("127.0.0.1", "123456789")},
    130 	{"ip:icmp", "127.0.0.1"},
    131 
    132 	{"unix", "/path/to/somewhere"},
    133 	{"unixgram", "/path/to/somewhere"},
    134 	{"unixpacket", "/path/to/somewhere"},
    135 }
    136 
    137 func TestDialError(t *testing.T) {
    138 	switch runtime.GOOS {
    139 	case "plan9":
    140 		t.Skipf("%s does not have full support of socktest", runtime.GOOS)
    141 	}
    142 
    143 	origTestHookLookupIP := testHookLookupIP
    144 	defer func() { testHookLookupIP = origTestHookLookupIP }()
    145 	testHookLookupIP = func(ctx context.Context, fn func(context.Context, string) ([]IPAddr, error), host string) ([]IPAddr, error) {
    146 		return nil, &DNSError{Err: "dial error test", Name: "name", Server: "server", IsTimeout: true}
    147 	}
    148 	sw.Set(socktest.FilterConnect, func(so *socktest.Status) (socktest.AfterFilter, error) {
    149 		return nil, errOpNotSupported
    150 	})
    151 	defer sw.Set(socktest.FilterConnect, nil)
    152 
    153 	d := Dialer{Timeout: someTimeout}
    154 	for i, tt := range dialErrorTests {
    155 		c, err := d.Dial(tt.network, tt.address)
    156 		if err == nil {
    157 			t.Errorf("#%d: should fail; %s:%s->%s", i, c.LocalAddr().Network(), c.LocalAddr(), c.RemoteAddr())
    158 			c.Close()
    159 			continue
    160 		}
    161 		if tt.network == "tcp" || tt.network == "udp" {
    162 			nerr := err
    163 			if op, ok := nerr.(*OpError); ok {
    164 				nerr = op.Err
    165 			}
    166 			if sys, ok := nerr.(*os.SyscallError); ok {
    167 				nerr = sys.Err
    168 			}
    169 			if nerr == errOpNotSupported {
    170 				t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
    171 				continue
    172 			}
    173 		}
    174 		if c != nil {
    175 			t.Errorf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
    176 		}
    177 		if err = parseDialError(err); err != nil {
    178 			t.Errorf("#%d: %v", i, err)
    179 			continue
    180 		}
    181 	}
    182 }
    183 
    184 func TestProtocolDialError(t *testing.T) {
    185 	switch runtime.GOOS {
    186 	case "nacl", "solaris":
    187 		t.Skipf("not supported on %s", runtime.GOOS)
    188 	}
    189 
    190 	for _, network := range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
    191 		var err error
    192 		switch network {
    193 		case "tcp":
    194 			_, err = DialTCP(network, nil, &TCPAddr{Port: 1 << 16})
    195 		case "udp":
    196 			_, err = DialUDP(network, nil, &UDPAddr{Port: 1 << 16})
    197 		case "ip:4294967296":
    198 			_, err = DialIP(network, nil, nil)
    199 		case "unix", "unixpacket", "unixgram":
    200 			_, err = DialUnix(network, nil, &UnixAddr{Name: "//"})
    201 		}
    202 		if err == nil {
    203 			t.Errorf("%s: should fail", network)
    204 			continue
    205 		}
    206 		if err = parseDialError(err); err != nil {
    207 			t.Errorf("%s: %v", network, err)
    208 			continue
    209 		}
    210 	}
    211 }
    212 
    213 func TestDialAddrError(t *testing.T) {
    214 	switch runtime.GOOS {
    215 	case "nacl", "plan9":
    216 		t.Skipf("not supported on %s", runtime.GOOS)
    217 	}
    218 	if !supportsIPv4() || !supportsIPv6() {
    219 		t.Skip("both IPv4 and IPv6 are required")
    220 	}
    221 
    222 	for _, tt := range []struct {
    223 		network string
    224 		lit     string
    225 		addr    *TCPAddr
    226 	}{
    227 		{"tcp4", "::1", nil},
    228 		{"tcp4", "", &TCPAddr{IP: IPv6loopback}},
    229 		// We don't test the {"tcp6", "byte sequence", nil}
    230 		// case for now because there is no easy way to
    231 		// control name resolution.
    232 		{"tcp6", "", &TCPAddr{IP: IP{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}}},
    233 	} {
    234 		var err error
    235 		var c Conn
    236 		var op string
    237 		if tt.lit != "" {
    238 			c, err = Dial(tt.network, JoinHostPort(tt.lit, "0"))
    239 			op = fmt.Sprintf("Dial(%q, %q)", tt.network, JoinHostPort(tt.lit, "0"))
    240 		} else {
    241 			c, err = DialTCP(tt.network, nil, tt.addr)
    242 			op = fmt.Sprintf("DialTCP(%q, %q)", tt.network, tt.addr)
    243 		}
    244 		if err == nil {
    245 			c.Close()
    246 			t.Errorf("%s succeeded, want error", op)
    247 			continue
    248 		}
    249 		if perr := parseDialError(err); perr != nil {
    250 			t.Errorf("%s: %v", op, perr)
    251 			continue
    252 		}
    253 		operr := err.(*OpError).Err
    254 		aerr, ok := operr.(*AddrError)
    255 		if !ok {
    256 			t.Errorf("%s: %v is %T, want *AddrError", op, err, operr)
    257 			continue
    258 		}
    259 		want := tt.lit
    260 		if tt.lit == "" {
    261 			want = tt.addr.IP.String()
    262 		}
    263 		if aerr.Addr != want {
    264 			t.Errorf("%s: %v, error Addr=%q, want %q", op, err, aerr.Addr, want)
    265 		}
    266 	}
    267 }
    268 
    269 var listenErrorTests = []struct {
    270 	network, address string
    271 }{
    272 	{"foo", ""},
    273 	{"bar", "baz"},
    274 	{"datakit", "mh/astro/r70"},
    275 	{"tcp", "127.0.0.1:"},
    276 	{"tcp", "no-such-name:80"},
    277 	{"tcp", "mh/astro/r70:http"},
    278 
    279 	{"tcp", JoinHostPort("127.0.0.1", "-1")},
    280 	{"tcp", JoinHostPort("127.0.0.1", "123456789")},
    281 
    282 	{"unix", "/path/to/somewhere"},
    283 	{"unixpacket", "/path/to/somewhere"},
    284 }
    285 
    286 func TestListenError(t *testing.T) {
    287 	switch runtime.GOOS {
    288 	case "plan9":
    289 		t.Skipf("%s does not have full support of socktest", runtime.GOOS)
    290 	}
    291 
    292 	origTestHookLookupIP := testHookLookupIP
    293 	defer func() { testHookLookupIP = origTestHookLookupIP }()
    294 	testHookLookupIP = func(_ context.Context, fn func(context.Context, string) ([]IPAddr, error), host string) ([]IPAddr, error) {
    295 		return nil, &DNSError{Err: "listen error test", Name: "name", Server: "server", IsTimeout: true}
    296 	}
    297 	sw.Set(socktest.FilterListen, func(so *socktest.Status) (socktest.AfterFilter, error) {
    298 		return nil, errOpNotSupported
    299 	})
    300 	defer sw.Set(socktest.FilterListen, nil)
    301 
    302 	for i, tt := range listenErrorTests {
    303 		ln, err := Listen(tt.network, tt.address)
    304 		if err == nil {
    305 			t.Errorf("#%d: should fail; %s:%s->", i, ln.Addr().Network(), ln.Addr())
    306 			ln.Close()
    307 			continue
    308 		}
    309 		if tt.network == "tcp" {
    310 			nerr := err
    311 			if op, ok := nerr.(*OpError); ok {
    312 				nerr = op.Err
    313 			}
    314 			if sys, ok := nerr.(*os.SyscallError); ok {
    315 				nerr = sys.Err
    316 			}
    317 			if nerr == errOpNotSupported {
    318 				t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
    319 				continue
    320 			}
    321 		}
    322 		if ln != nil {
    323 			t.Errorf("Listen returned non-nil interface %T(%v) with err != nil", ln, ln)
    324 		}
    325 		if err = parseDialError(err); err != nil {
    326 			t.Errorf("#%d: %v", i, err)
    327 			continue
    328 		}
    329 	}
    330 }
    331 
    332 var listenPacketErrorTests = []struct {
    333 	network, address string
    334 }{
    335 	{"foo", ""},
    336 	{"bar", "baz"},
    337 	{"datakit", "mh/astro/r70"},
    338 	{"udp", "127.0.0.1:"},
    339 	{"udp", "no-such-name:80"},
    340 	{"udp", "mh/astro/r70:http"},
    341 
    342 	{"udp", JoinHostPort("127.0.0.1", "-1")},
    343 	{"udp", JoinHostPort("127.0.0.1", "123456789")},
    344 }
    345 
    346 func TestListenPacketError(t *testing.T) {
    347 	switch runtime.GOOS {
    348 	case "plan9":
    349 		t.Skipf("%s does not have full support of socktest", runtime.GOOS)
    350 	}
    351 
    352 	origTestHookLookupIP := testHookLookupIP
    353 	defer func() { testHookLookupIP = origTestHookLookupIP }()
    354 	testHookLookupIP = func(_ context.Context, fn func(context.Context, string) ([]IPAddr, error), host string) ([]IPAddr, error) {
    355 		return nil, &DNSError{Err: "listen error test", Name: "name", Server: "server", IsTimeout: true}
    356 	}
    357 
    358 	for i, tt := range listenPacketErrorTests {
    359 		c, err := ListenPacket(tt.network, tt.address)
    360 		if err == nil {
    361 			t.Errorf("#%d: should fail; %s:%s->", i, c.LocalAddr().Network(), c.LocalAddr())
    362 			c.Close()
    363 			continue
    364 		}
    365 		if c != nil {
    366 			t.Errorf("ListenPacket returned non-nil interface %T(%v) with err != nil", c, c)
    367 		}
    368 		if err = parseDialError(err); err != nil {
    369 			t.Errorf("#%d: %v", i, err)
    370 			continue
    371 		}
    372 	}
    373 }
    374 
    375 func TestProtocolListenError(t *testing.T) {
    376 	switch runtime.GOOS {
    377 	case "nacl", "plan9":
    378 		t.Skipf("not supported on %s", runtime.GOOS)
    379 	}
    380 
    381 	for _, network := range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
    382 		var err error
    383 		switch network {
    384 		case "tcp":
    385 			_, err = ListenTCP(network, &TCPAddr{Port: 1 << 16})
    386 		case "udp":
    387 			_, err = ListenUDP(network, &UDPAddr{Port: 1 << 16})
    388 		case "ip:4294967296":
    389 			_, err = ListenIP(network, nil)
    390 		case "unix", "unixpacket":
    391 			_, err = ListenUnix(network, &UnixAddr{Name: "//"})
    392 		case "unixgram":
    393 			_, err = ListenUnixgram(network, &UnixAddr{Name: "//"})
    394 		}
    395 		if err == nil {
    396 			t.Errorf("%s: should fail", network)
    397 			continue
    398 		}
    399 		if err = parseDialError(err); err != nil {
    400 			t.Errorf("%s: %v", network, err)
    401 			continue
    402 		}
    403 	}
    404 }
    405 
    406 // parseReadError parses nestedErr and reports whether it is a valid
    407 // error value from Read functions.
    408 // It returns nil when nestedErr is valid.
    409 func parseReadError(nestedErr error) error {
    410 	if nestedErr == nil {
    411 		return nil
    412 	}
    413 
    414 	switch err := nestedErr.(type) {
    415 	case *OpError:
    416 		if err := err.isValid(); err != nil {
    417 			return err
    418 		}
    419 		nestedErr = err.Err
    420 		goto second
    421 	}
    422 	if nestedErr == io.EOF {
    423 		return nil
    424 	}
    425 	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
    426 
    427 second:
    428 	if isPlatformError(nestedErr) {
    429 		return nil
    430 	}
    431 	switch err := nestedErr.(type) {
    432 	case *os.SyscallError:
    433 		nestedErr = err.Err
    434 		goto third
    435 	}
    436 	switch nestedErr {
    437 	case poll.ErrNetClosing, poll.ErrTimeout:
    438 		return nil
    439 	}
    440 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
    441 
    442 third:
    443 	if isPlatformError(nestedErr) {
    444 		return nil
    445 	}
    446 	return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
    447 }
    448 
    449 // parseWriteError parses nestedErr and reports whether it is a valid
    450 // error value from Write functions.
    451 // It returns nil when nestedErr is valid.
    452 func parseWriteError(nestedErr error) error {
    453 	if nestedErr == nil {
    454 		return nil
    455 	}
    456 
    457 	switch err := nestedErr.(type) {
    458 	case *OpError:
    459 		if err := err.isValid(); err != nil {
    460 			return err
    461 		}
    462 		nestedErr = err.Err
    463 		goto second
    464 	}
    465 	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
    466 
    467 second:
    468 	if isPlatformError(nestedErr) {
    469 		return nil
    470 	}
    471 	switch err := nestedErr.(type) {
    472 	case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *poll.TimeoutError, UnknownNetworkError:
    473 		return nil
    474 	case *os.SyscallError:
    475 		nestedErr = err.Err
    476 		goto third
    477 	}
    478 	switch nestedErr {
    479 	case errCanceled, poll.ErrNetClosing, errMissingAddress, poll.ErrTimeout, ErrWriteToConnected, io.ErrUnexpectedEOF:
    480 		return nil
    481 	}
    482 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
    483 
    484 third:
    485 	if isPlatformError(nestedErr) {
    486 		return nil
    487 	}
    488 	return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
    489 }
    490 
    491 // parseCloseError parses nestedErr and reports whether it is a valid
    492 // error value from Close functions.
    493 // It returns nil when nestedErr is valid.
    494 func parseCloseError(nestedErr error, isShutdown bool) error {
    495 	if nestedErr == nil {
    496 		return nil
    497 	}
    498 
    499 	// Because historically we have not exported the error that we
    500 	// return for an operation on a closed network connection,
    501 	// there are programs that test for the exact error string.
    502 	// Verify that string here so that we don't break those
    503 	// programs unexpectedly. See issues #4373 and #19252.
    504 	want := "use of closed network connection"
    505 	if !isShutdown && !strings.Contains(nestedErr.Error(), want) {
    506 		return fmt.Errorf("error string %q does not contain expected string %q", nestedErr, want)
    507 	}
    508 
    509 	switch err := nestedErr.(type) {
    510 	case *OpError:
    511 		if err := err.isValid(); err != nil {
    512 			return err
    513 		}
    514 		nestedErr = err.Err
    515 		goto second
    516 	}
    517 	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
    518 
    519 second:
    520 	if isPlatformError(nestedErr) {
    521 		return nil
    522 	}
    523 	switch err := nestedErr.(type) {
    524 	case *os.SyscallError:
    525 		nestedErr = err.Err
    526 		goto third
    527 	case *os.PathError: // for Plan 9
    528 		nestedErr = err.Err
    529 		goto third
    530 	}
    531 	switch nestedErr {
    532 	case poll.ErrNetClosing:
    533 		return nil
    534 	}
    535 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
    536 
    537 third:
    538 	if isPlatformError(nestedErr) {
    539 		return nil
    540 	}
    541 	switch nestedErr {
    542 	case os.ErrClosed: // for Plan 9
    543 		return nil
    544 	}
    545 	return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
    546 }
    547 
    548 func TestCloseError(t *testing.T) {
    549 	ln, err := newLocalListener("tcp")
    550 	if err != nil {
    551 		t.Fatal(err)
    552 	}
    553 	defer ln.Close()
    554 	c, err := Dial(ln.Addr().Network(), ln.Addr().String())
    555 	if err != nil {
    556 		t.Fatal(err)
    557 	}
    558 	defer c.Close()
    559 
    560 	for i := 0; i < 3; i++ {
    561 		err = c.(*TCPConn).CloseRead()
    562 		if perr := parseCloseError(err, true); perr != nil {
    563 			t.Errorf("#%d: %v", i, perr)
    564 		}
    565 	}
    566 	for i := 0; i < 3; i++ {
    567 		err = c.(*TCPConn).CloseWrite()
    568 		if perr := parseCloseError(err, true); perr != nil {
    569 			t.Errorf("#%d: %v", i, perr)
    570 		}
    571 	}
    572 	for i := 0; i < 3; i++ {
    573 		err = c.Close()
    574 		if perr := parseCloseError(err, false); perr != nil {
    575 			t.Errorf("#%d: %v", i, perr)
    576 		}
    577 		err = ln.Close()
    578 		if perr := parseCloseError(err, false); perr != nil {
    579 			t.Errorf("#%d: %v", i, perr)
    580 		}
    581 	}
    582 
    583 	pc, err := ListenPacket("udp", "127.0.0.1:0")
    584 	if err != nil {
    585 		t.Fatal(err)
    586 	}
    587 	defer pc.Close()
    588 
    589 	for i := 0; i < 3; i++ {
    590 		err = pc.Close()
    591 		if perr := parseCloseError(err, false); perr != nil {
    592 			t.Errorf("#%d: %v", i, perr)
    593 		}
    594 	}
    595 }
    596 
    597 // parseAcceptError parses nestedErr and reports whether it is a valid
    598 // error value from Accept functions.
    599 // It returns nil when nestedErr is valid.
    600 func parseAcceptError(nestedErr error) error {
    601 	if nestedErr == nil {
    602 		return nil
    603 	}
    604 
    605 	switch err := nestedErr.(type) {
    606 	case *OpError:
    607 		if err := err.isValid(); err != nil {
    608 			return err
    609 		}
    610 		nestedErr = err.Err
    611 		goto second
    612 	}
    613 	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
    614 
    615 second:
    616 	if isPlatformError(nestedErr) {
    617 		return nil
    618 	}
    619 	switch err := nestedErr.(type) {
    620 	case *os.SyscallError:
    621 		nestedErr = err.Err
    622 		goto third
    623 	case *os.PathError: // for Plan 9
    624 		nestedErr = err.Err
    625 		goto third
    626 	}
    627 	switch nestedErr {
    628 	case poll.ErrNetClosing, poll.ErrTimeout:
    629 		return nil
    630 	}
    631 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
    632 
    633 third:
    634 	if isPlatformError(nestedErr) {
    635 		return nil
    636 	}
    637 	return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
    638 }
    639 
    640 func TestAcceptError(t *testing.T) {
    641 	handler := func(ls *localServer, ln Listener) {
    642 		for {
    643 			ln.(*TCPListener).SetDeadline(time.Now().Add(5 * time.Millisecond))
    644 			c, err := ln.Accept()
    645 			if perr := parseAcceptError(err); perr != nil {
    646 				t.Error(perr)
    647 			}
    648 			if err != nil {
    649 				if c != nil {
    650 					t.Errorf("Accept returned non-nil interface %T(%v) with err != nil", c, c)
    651 				}
    652 				if nerr, ok := err.(Error); !ok || (!nerr.Timeout() && !nerr.Temporary()) {
    653 					return
    654 				}
    655 				continue
    656 			}
    657 			c.Close()
    658 		}
    659 	}
    660 	ls, err := newLocalServer("tcp")
    661 	if err != nil {
    662 		t.Fatal(err)
    663 	}
    664 	if err := ls.buildup(handler); err != nil {
    665 		ls.teardown()
    666 		t.Fatal(err)
    667 	}
    668 
    669 	time.Sleep(100 * time.Millisecond)
    670 	ls.teardown()
    671 }
    672 
    673 // parseCommonError parses nestedErr and reports whether it is a valid
    674 // error value from miscellaneous functions.
    675 // It returns nil when nestedErr is valid.
    676 func parseCommonError(nestedErr error) error {
    677 	if nestedErr == nil {
    678 		return nil
    679 	}
    680 
    681 	switch err := nestedErr.(type) {
    682 	case *OpError:
    683 		if err := err.isValid(); err != nil {
    684 			return err
    685 		}
    686 		nestedErr = err.Err
    687 		goto second
    688 	}
    689 	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
    690 
    691 second:
    692 	if isPlatformError(nestedErr) {
    693 		return nil
    694 	}
    695 	switch err := nestedErr.(type) {
    696 	case *os.SyscallError:
    697 		nestedErr = err.Err
    698 		goto third
    699 	case *os.LinkError:
    700 		nestedErr = err.Err
    701 		goto third
    702 	case *os.PathError:
    703 		nestedErr = err.Err
    704 		goto third
    705 	}
    706 	switch nestedErr {
    707 	case poll.ErrNetClosing:
    708 		return nil
    709 	}
    710 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
    711 
    712 third:
    713 	if isPlatformError(nestedErr) {
    714 		return nil
    715 	}
    716 	return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
    717 }
    718 
    719 func TestFileError(t *testing.T) {
    720 	switch runtime.GOOS {
    721 	case "windows":
    722 		t.Skipf("not supported on %s", runtime.GOOS)
    723 	}
    724 
    725 	f, err := ioutil.TempFile("", "go-nettest")
    726 	if err != nil {
    727 		t.Fatal(err)
    728 	}
    729 	defer os.Remove(f.Name())
    730 	defer f.Close()
    731 
    732 	c, err := FileConn(f)
    733 	if err != nil {
    734 		if c != nil {
    735 			t.Errorf("FileConn returned non-nil interface %T(%v) with err != nil", c, c)
    736 		}
    737 		if perr := parseCommonError(err); perr != nil {
    738 			t.Error(perr)
    739 		}
    740 	} else {
    741 		c.Close()
    742 		t.Error("should fail")
    743 	}
    744 	ln, err := FileListener(f)
    745 	if err != nil {
    746 		if ln != nil {
    747 			t.Errorf("FileListener returned non-nil interface %T(%v) with err != nil", ln, ln)
    748 		}
    749 		if perr := parseCommonError(err); perr != nil {
    750 			t.Error(perr)
    751 		}
    752 	} else {
    753 		ln.Close()
    754 		t.Error("should fail")
    755 	}
    756 	pc, err := FilePacketConn(f)
    757 	if err != nil {
    758 		if pc != nil {
    759 			t.Errorf("FilePacketConn returned non-nil interface %T(%v) with err != nil", pc, pc)
    760 		}
    761 		if perr := parseCommonError(err); perr != nil {
    762 			t.Error(perr)
    763 		}
    764 	} else {
    765 		pc.Close()
    766 		t.Error("should fail")
    767 	}
    768 
    769 	ln, err = newLocalListener("tcp")
    770 	if err != nil {
    771 		t.Fatal(err)
    772 	}
    773 
    774 	for i := 0; i < 3; i++ {
    775 		f, err := ln.(*TCPListener).File()
    776 		if err != nil {
    777 			if perr := parseCommonError(err); perr != nil {
    778 				t.Error(perr)
    779 			}
    780 		} else {
    781 			f.Close()
    782 		}
    783 		ln.Close()
    784 	}
    785 }
    786 
    787 func parseLookupPortError(nestedErr error) error {
    788 	if nestedErr == nil {
    789 		return nil
    790 	}
    791 
    792 	switch nestedErr.(type) {
    793 	case *AddrError, *DNSError:
    794 		return nil
    795 	case *os.PathError: // for Plan 9
    796 		return nil
    797 	}
    798 	return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
    799 }
    800