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