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