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