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.
13 "net/internal/socktest"
21 func (e
*OpError
) isValid() error
{
23 return fmt
.Errorf("OpError.Op is empty: %v", e
)
26 return fmt
.Errorf("OpError.Net is empty: %v", e
)
28 for _
, addr
:= range []Addr
{e
.Source
, e
.Addr
} {
29 switch addr
:= addr
.(type) {
33 return fmt
.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr
, e
)
37 return fmt
.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr
, e
)
41 return fmt
.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr
, e
)
45 return fmt
.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr
, e
)
49 return fmt
.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr
, e
)
53 return fmt
.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr
, e
)
57 return fmt
.Errorf("OpError.Source or Addr is empty: %#v, %v", addr
, e
)
60 return fmt
.Errorf("OpError.Source or Addr is unknown type: %T, %v", addr
, e
)
64 return fmt
.Errorf("OpError.Err is empty: %v", e
)
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
{
77 switch err
:= nestedErr
.(type) {
79 if err
:= err
.isValid(); err
!= nil {
85 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)
88 if isPlatformError(nestedErr
) {
91 switch err
:= nestedErr
.(type) {
92 case *AddrError
, addrinfoErrno
, *DNSError
, InvalidAddrError
, *ParseError
, *poll
.TimeoutError
, UnknownNetworkError
:
94 case *os
.SyscallError
:
97 case *os
.PathError
: // for Plan 9
102 case errCanceled
, poll
.ErrNetClosing
, errMissingAddress
, errNoSuitableAddress
,
103 context
.DeadlineExceeded
, context
.Canceled
:
106 return fmt
.Errorf("unexpected type on 2nd nested level: %T", nestedErr
)
109 if isPlatformError(nestedErr
) {
112 return fmt
.Errorf("unexpected type on 3rd nested level: %T", nestedErr
)
115 var dialErrorTests
= []struct {
116 network
, address
string
120 {"datakit", "mh/astro/r70"},
122 {"tcp", "127.0.0.1:☺"},
123 {"tcp", "no-such-name:80"},
124 {"tcp", "mh/astro/r70:http"},
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"},
132 {"unix", "/path/to/somewhere"},
133 {"unixgram", "/path/to/somewhere"},
134 {"unixpacket", "/path/to/somewhere"},
137 func TestDialError(t
*testing
.T
) {
138 switch runtime
.GOOS
{
140 t
.Skipf("%s does not have full support of socktest", runtime
.GOOS
)
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}
148 sw
.Set(socktest
.FilterConnect
, func(so
*socktest
.Status
) (socktest
.AfterFilter
, error
) {
149 return nil, errOpNotSupported
151 defer sw
.Set(socktest
.FilterConnect
, nil)
153 d
:= Dialer
{Timeout
: someTimeout
}
154 for i
, tt
:= range dialErrorTests
{
155 c
, err
:= d
.Dial(tt
.network
, tt
.address
)
157 t
.Errorf("#%d: should fail; %s:%s->%s", i
, c
.LocalAddr().Network(), c
.LocalAddr(), c
.RemoteAddr())
161 if tt
.network
== "tcp" || tt
.network
== "udp" {
163 if op
, ok
:= nerr
.(*OpError
); ok
{
166 if sys
, ok
:= nerr
.(*os
.SyscallError
); ok
{
169 if nerr
== errOpNotSupported
{
170 t
.Errorf("#%d: should fail without %v; %s:%s->", i
, nerr
, tt
.network
, tt
.address
)
175 t
.Errorf("Dial returned non-nil interface %T(%v) with err != nil", c
, c
)
177 if err
= parseDialError(err
); err
!= nil {
178 t
.Errorf("#%d: %v", i
, err
)
184 func TestProtocolDialError(t
*testing
.T
) {
185 switch runtime
.GOOS
{
186 case "nacl", "solaris":
187 t
.Skipf("not supported on %s", runtime
.GOOS
)
190 for _
, network
:= range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
194 _
, err
= DialTCP(network
, nil, &TCPAddr
{Port
: 1 << 16})
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
: "//"})
203 t
.Errorf("%s: should fail", network
)
206 if err
= parseDialError(err
); err
!= nil {
207 t
.Errorf("%s: %v", network
, err
)
213 func TestDialAddrError(t
*testing
.T
) {
214 switch runtime
.GOOS
{
215 case "nacl", "plan9":
216 t
.Skipf("not supported on %s", runtime
.GOOS
)
218 if !supportsIPv4() ||
!supportsIPv6() {
219 t
.Skip("both IPv4 and IPv6 are required")
222 for _
, tt
:= range []struct {
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}}},
238 c
, err
= Dial(tt
.network
, JoinHostPort(tt
.lit
, "0"))
239 op
= fmt
.Sprintf("Dial(%q, %q)", tt
.network
, JoinHostPort(tt
.lit
, "0"))
241 c
, err
= DialTCP(tt
.network
, nil, tt
.addr
)
242 op
= fmt
.Sprintf("DialTCP(%q, %q)", tt
.network
, tt
.addr
)
246 t
.Errorf("%s succeeded, want error", op
)
249 if perr
:= parseDialError(err
); perr
!= nil {
250 t
.Errorf("%s: %v", op
, perr
)
253 operr
:= err
.(*OpError
).Err
254 aerr
, ok
:= operr
.(*AddrError
)
256 t
.Errorf("%s: %v is %T, want *AddrError", op
, err
, operr
)
261 want
= tt
.addr
.IP
.String()
263 if aerr
.Addr
!= want
{
264 t
.Errorf("%s: %v, error Addr=%q, want %q", op
, err
, aerr
.Addr
, want
)
269 var listenErrorTests
= []struct {
270 network
, address
string
274 {"datakit", "mh/astro/r70"},
275 {"tcp", "127.0.0.1:☺"},
276 {"tcp", "no-such-name:80"},
277 {"tcp", "mh/astro/r70:http"},
279 {"tcp", JoinHostPort("127.0.0.1", "-1")},
280 {"tcp", JoinHostPort("127.0.0.1", "123456789")},
282 {"unix", "/path/to/somewhere"},
283 {"unixpacket", "/path/to/somewhere"},
286 func TestListenError(t
*testing
.T
) {
287 switch runtime
.GOOS
{
289 t
.Skipf("%s does not have full support of socktest", runtime
.GOOS
)
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}
297 sw
.Set(socktest
.FilterListen
, func(so
*socktest
.Status
) (socktest
.AfterFilter
, error
) {
298 return nil, errOpNotSupported
300 defer sw
.Set(socktest
.FilterListen
, nil)
302 for i
, tt
:= range listenErrorTests
{
303 ln
, err
:= Listen(tt
.network
, tt
.address
)
305 t
.Errorf("#%d: should fail; %s:%s->", i
, ln
.Addr().Network(), ln
.Addr())
309 if tt
.network
== "tcp" {
311 if op
, ok
:= nerr
.(*OpError
); ok
{
314 if sys
, ok
:= nerr
.(*os
.SyscallError
); ok
{
317 if nerr
== errOpNotSupported
{
318 t
.Errorf("#%d: should fail without %v; %s:%s->", i
, nerr
, tt
.network
, tt
.address
)
323 t
.Errorf("Listen returned non-nil interface %T(%v) with err != nil", ln
, ln
)
325 if err
= parseDialError(err
); err
!= nil {
326 t
.Errorf("#%d: %v", i
, err
)
332 var listenPacketErrorTests
= []struct {
333 network
, address
string
337 {"datakit", "mh/astro/r70"},
338 {"udp", "127.0.0.1:☺"},
339 {"udp", "no-such-name:80"},
340 {"udp", "mh/astro/r70:http"},
342 {"udp", JoinHostPort("127.0.0.1", "-1")},
343 {"udp", JoinHostPort("127.0.0.1", "123456789")},
346 func TestListenPacketError(t
*testing
.T
) {
347 switch runtime
.GOOS
{
349 t
.Skipf("%s does not have full support of socktest", runtime
.GOOS
)
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}
358 for i
, tt
:= range listenPacketErrorTests
{
359 c
, err
:= ListenPacket(tt
.network
, tt
.address
)
361 t
.Errorf("#%d: should fail; %s:%s->", i
, c
.LocalAddr().Network(), c
.LocalAddr())
366 t
.Errorf("ListenPacket returned non-nil interface %T(%v) with err != nil", c
, c
)
368 if err
= parseDialError(err
); err
!= nil {
369 t
.Errorf("#%d: %v", i
, err
)
375 func TestProtocolListenError(t
*testing
.T
) {
376 switch runtime
.GOOS
{
377 case "nacl", "plan9":
378 t
.Skipf("not supported on %s", runtime
.GOOS
)
381 for _
, network
:= range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
385 _
, err
= ListenTCP(network
, &TCPAddr
{Port
: 1 << 16})
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
: "//"})
393 _
, err
= ListenUnixgram(network
, &UnixAddr
{Name
: "//"})
396 t
.Errorf("%s: should fail", network
)
399 if err
= parseDialError(err
); err
!= nil {
400 t
.Errorf("%s: %v", network
, err
)
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 {
414 switch err
:= nestedErr
.(type) {
416 if err
:= err
.isValid(); err
!= nil {
422 if nestedErr
== io
.EOF
{
425 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)
428 if isPlatformError(nestedErr
) {
431 switch err
:= nestedErr
.(type) {
432 case *os
.SyscallError
:
437 case poll
.ErrNetClosing
, poll
.ErrTimeout
:
440 return fmt
.Errorf("unexpected type on 2nd nested level: %T", nestedErr
)
443 if isPlatformError(nestedErr
) {
446 return fmt
.Errorf("unexpected type on 3rd nested level: %T", nestedErr
)
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 {
457 switch err
:= nestedErr
.(type) {
459 if err
:= err
.isValid(); err
!= nil {
465 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)
468 if isPlatformError(nestedErr
) {
471 switch err
:= nestedErr
.(type) {
472 case *AddrError
, addrinfoErrno
, *DNSError
, InvalidAddrError
, *ParseError
, *poll
.TimeoutError
, UnknownNetworkError
:
474 case *os
.SyscallError
:
479 case errCanceled
, poll
.ErrNetClosing
, errMissingAddress
, poll
.ErrTimeout
, ErrWriteToConnected
, io
.ErrUnexpectedEOF
:
482 return fmt
.Errorf("unexpected type on 2nd nested level: %T", nestedErr
)
485 if isPlatformError(nestedErr
) {
488 return fmt
.Errorf("unexpected type on 3rd nested level: %T", nestedErr
)
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 {
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
)
509 switch err
:= nestedErr
.(type) {
511 if err
:= err
.isValid(); err
!= nil {
517 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)
520 if isPlatformError(nestedErr
) {
523 switch err
:= nestedErr
.(type) {
524 case *os
.SyscallError
:
527 case *os
.PathError
: // for Plan 9
532 case poll
.ErrNetClosing
:
535 return fmt
.Errorf("unexpected type on 2nd nested level: %T", nestedErr
)
538 if isPlatformError(nestedErr
) {
542 case os
.ErrClosed
: // for Plan 9
545 return fmt
.Errorf("unexpected type on 3rd nested level: %T", nestedErr
)
548 func TestCloseError(t
*testing
.T
) {
549 ln
, err
:= newLocalListener("tcp")
554 c
, err
:= Dial(ln
.Addr().Network(), ln
.Addr().String())
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
)
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
)
572 for i
:= 0; i
< 3; i
++ {
574 if perr
:= parseCloseError(err
, false); perr
!= nil {
575 t
.Errorf("#%d: %v", i
, perr
)
578 if perr
:= parseCloseError(err
, false); perr
!= nil {
579 t
.Errorf("#%d: %v", i
, perr
)
583 pc
, err
:= ListenPacket("udp", "127.0.0.1:0")
589 for i
:= 0; i
< 3; i
++ {
591 if perr
:= parseCloseError(err
, false); perr
!= nil {
592 t
.Errorf("#%d: %v", i
, perr
)
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 {
605 switch err
:= nestedErr
.(type) {
607 if err
:= err
.isValid(); err
!= nil {
613 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)
616 if isPlatformError(nestedErr
) {
619 switch err
:= nestedErr
.(type) {
620 case *os
.SyscallError
:
623 case *os
.PathError
: // for Plan 9
628 case poll
.ErrNetClosing
, poll
.ErrTimeout
:
631 return fmt
.Errorf("unexpected type on 2nd nested level: %T", nestedErr
)
634 if isPlatformError(nestedErr
) {
637 return fmt
.Errorf("unexpected type on 3rd nested level: %T", nestedErr
)
640 func TestAcceptError(t
*testing
.T
) {
641 handler
:= func(ls
*localServer
, ln Listener
) {
643 ln
.(*TCPListener
).SetDeadline(time
.Now().Add(5 * time
.Millisecond
))
644 c
, err
:= ln
.Accept()
645 if perr
:= parseAcceptError(err
); perr
!= nil {
650 t
.Errorf("Accept returned non-nil interface %T(%v) with err != nil", c
, c
)
652 if nerr
, ok
:= err
.(Error
); !ok ||
(!nerr
.Timeout() && !nerr
.Temporary()) {
660 ls
, err
:= newLocalServer("tcp")
664 if err
:= ls
.buildup(handler
); err
!= nil {
669 time
.Sleep(100 * time
.Millisecond
)
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 {
681 switch err
:= nestedErr
.(type) {
683 if err
:= err
.isValid(); err
!= nil {
689 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)
692 if isPlatformError(nestedErr
) {
695 switch err
:= nestedErr
.(type) {
696 case *os
.SyscallError
:
707 case poll
.ErrNetClosing
:
710 return fmt
.Errorf("unexpected type on 2nd nested level: %T", nestedErr
)
713 if isPlatformError(nestedErr
) {
716 return fmt
.Errorf("unexpected type on 3rd nested level: %T", nestedErr
)
719 func TestFileError(t
*testing
.T
) {
720 switch runtime
.GOOS
{
722 t
.Skipf("not supported on %s", runtime
.GOOS
)
725 f
, err
:= ioutil
.TempFile("", "go-nettest")
729 defer os
.Remove(f
.Name())
732 c
, err
:= FileConn(f
)
735 t
.Errorf("FileConn returned non-nil interface %T(%v) with err != nil", c
, c
)
737 if perr
:= parseCommonError(err
); perr
!= nil {
742 t
.Error("should fail")
744 ln
, err
:= FileListener(f
)
747 t
.Errorf("FileListener returned non-nil interface %T(%v) with err != nil", ln
, ln
)
749 if perr
:= parseCommonError(err
); perr
!= nil {
754 t
.Error("should fail")
756 pc
, err
:= FilePacketConn(f
)
759 t
.Errorf("FilePacketConn returned non-nil interface %T(%v) with err != nil", pc
, pc
)
761 if perr
:= parseCommonError(err
); perr
!= nil {
766 t
.Error("should fail")
769 ln
, err
= newLocalListener("tcp")
774 for i
:= 0; i
< 3; i
++ {
775 f
, err
:= ln
.(*TCPListener
).File()
777 if perr
:= parseCommonError(err
); perr
!= nil {
787 func parseLookupPortError(nestedErr error
) error
{
788 if nestedErr
== nil {
792 switch nestedErr
.(type) {
793 case *AddrError
, *DNSError
:
795 case *os
.PathError
: // for Plan 9
798 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)