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