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.
12 "net/internal/socktest"
19 func (e
*OpError
) isValid() error
{
21 return fmt
.Errorf("OpError.Op is empty: %v", e
)
24 return fmt
.Errorf("OpError.Net is empty: %v", e
)
26 for _
, addr
:= range []Addr
{e
.Source
, e
.Addr
} {
27 switch addr
:= addr
.(type) {
31 return fmt
.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr
, e
)
35 return fmt
.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr
, e
)
39 return fmt
.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr
, e
)
43 return fmt
.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr
, e
)
47 return fmt
.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr
, e
)
51 return fmt
.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr
, e
)
55 return fmt
.Errorf("OpError.Source or Addr is empty: %#v, %v", addr
, e
)
58 return fmt
.Errorf("OpError.Source or Addr is unknown type: %T, %v", addr
, e
)
62 return fmt
.Errorf("OpError.Err is empty: %v", e
)
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
{
75 switch err
:= nestedErr
.(type) {
77 if err
:= err
.isValid(); err
!= nil {
83 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)
86 if isPlatformError(nestedErr
) {
89 switch err
:= nestedErr
.(type) {
90 case *AddrError
, addrinfoErrno
, *DNSError
, InvalidAddrError
, *ParseError
, *timeoutError
, UnknownNetworkError
:
92 case *os
.SyscallError
:
95 case *os
.PathError
: // for Plan 9
100 case errCanceled
, errClosing
, errMissingAddress
, errNoSuitableAddress
,
101 context
.DeadlineExceeded
, context
.Canceled
:
104 return fmt
.Errorf("unexpected type on 2nd nested level: %T", nestedErr
)
107 if isPlatformError(nestedErr
) {
110 return fmt
.Errorf("unexpected type on 3rd nested level: %T", nestedErr
)
113 var dialErrorTests
= []struct {
114 network
, address
string
118 {"datakit", "mh/astro/r70"},
120 {"tcp", "127.0.0.1:☺"},
121 {"tcp", "no-such-name:80"},
122 {"tcp", "mh/astro/r70:http"},
124 {"tcp", JoinHostPort("127.0.0.1", "-1")},
125 {"tcp", JoinHostPort("127.0.0.1", "123456789")},
126 {"udp", JoinHostPort("127.0.0.1", "-1")},
127 {"udp", JoinHostPort("127.0.0.1", "123456789")},
128 {"ip:icmp", "127.0.0.1"},
130 {"unix", "/path/to/somewhere"},
131 {"unixgram", "/path/to/somewhere"},
132 {"unixpacket", "/path/to/somewhere"},
135 func TestDialError(t
*testing
.T
) {
136 switch runtime
.GOOS
{
138 t
.Skipf("%s does not have full support of socktest", runtime
.GOOS
)
141 origTestHookLookupIP
:= testHookLookupIP
142 defer func() { testHookLookupIP
= origTestHookLookupIP
}()
143 testHookLookupIP
= func(ctx context
.Context
, fn
func(context
.Context
, string) ([]IPAddr
, error
), host
string) ([]IPAddr
, error
) {
144 return nil, &DNSError
{Err
: "dial error test", Name
: "name", Server
: "server", IsTimeout
: true}
146 sw
.Set(socktest
.FilterConnect
, func(so
*socktest
.Status
) (socktest
.AfterFilter
, error
) {
147 return nil, errOpNotSupported
149 defer sw
.Set(socktest
.FilterConnect
, nil)
151 d
:= Dialer
{Timeout
: someTimeout
}
152 for i
, tt
:= range dialErrorTests
{
153 c
, err
:= d
.Dial(tt
.network
, tt
.address
)
155 t
.Errorf("#%d: should fail; %s:%s->%s", i
, c
.LocalAddr().Network(), c
.LocalAddr(), c
.RemoteAddr())
159 if tt
.network
== "tcp" || tt
.network
== "udp" {
161 if op
, ok
:= nerr
.(*OpError
); ok
{
164 if sys
, ok
:= nerr
.(*os
.SyscallError
); ok
{
167 if nerr
== errOpNotSupported
{
168 t
.Errorf("#%d: should fail without %v; %s:%s->", i
, nerr
, tt
.network
, tt
.address
)
173 t
.Errorf("Dial returned non-nil interface %T(%v) with err != nil", c
, c
)
175 if err
= parseDialError(err
); err
!= nil {
176 t
.Errorf("#%d: %v", i
, err
)
182 func TestProtocolDialError(t
*testing
.T
) {
183 switch runtime
.GOOS
{
184 case "nacl", "solaris":
185 t
.Skipf("not supported on %s", runtime
.GOOS
)
188 for _
, network
:= range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
192 _
, err
= DialTCP(network
, nil, &TCPAddr
{Port
: 1 << 16})
194 _
, err
= DialUDP(network
, nil, &UDPAddr
{Port
: 1 << 16})
195 case "ip:4294967296":
196 _
, err
= DialIP(network
, nil, nil)
197 case "unix", "unixpacket", "unixgram":
198 _
, err
= DialUnix(network
, nil, &UnixAddr
{Name
: "//"})
201 t
.Errorf("%s: should fail", network
)
204 if err
= parseDialError(err
); err
!= nil {
205 t
.Errorf("%s: %v", network
, err
)
211 func TestDialAddrError(t
*testing
.T
) {
212 switch runtime
.GOOS
{
213 case "nacl", "plan9":
214 t
.Skipf("not supported on %s", runtime
.GOOS
)
216 if !supportsIPv4 ||
!supportsIPv6
{
217 t
.Skip("both IPv4 and IPv6 are required")
220 for _
, tt
:= range []struct {
225 {"tcp4", "::1", nil},
226 {"tcp4", "", &TCPAddr
{IP
: IPv6loopback
}},
227 // We don't test the {"tcp6", "byte sequence", nil}
228 // case for now because there is no easy way to
229 // control name resolution.
230 {"tcp6", "", &TCPAddr
{IP
: IP
{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}}},
236 c
, err
= Dial(tt
.network
, JoinHostPort(tt
.lit
, "0"))
237 op
= fmt
.Sprintf("Dial(%q, %q)", tt
.network
, JoinHostPort(tt
.lit
, "0"))
239 c
, err
= DialTCP(tt
.network
, nil, tt
.addr
)
240 op
= fmt
.Sprintf("DialTCP(%q, %q)", tt
.network
, tt
.addr
)
244 t
.Errorf("%s succeeded, want error", op
)
247 if perr
:= parseDialError(err
); perr
!= nil {
248 t
.Errorf("%s: %v", op
, perr
)
251 operr
:= err
.(*OpError
).Err
252 aerr
, ok
:= operr
.(*AddrError
)
254 t
.Errorf("%s: %v is %T, want *AddrError", op
, err
, operr
)
259 want
= tt
.addr
.IP
.String()
261 if aerr
.Addr
!= want
{
262 t
.Errorf("%s: %v, error Addr=%q, want %q", op
, err
, aerr
.Addr
, want
)
267 var listenErrorTests
= []struct {
268 network
, address
string
272 {"datakit", "mh/astro/r70"},
273 {"tcp", "127.0.0.1:☺"},
274 {"tcp", "no-such-name:80"},
275 {"tcp", "mh/astro/r70:http"},
277 {"tcp", JoinHostPort("127.0.0.1", "-1")},
278 {"tcp", JoinHostPort("127.0.0.1", "123456789")},
280 {"unix", "/path/to/somewhere"},
281 {"unixpacket", "/path/to/somewhere"},
284 func TestListenError(t
*testing
.T
) {
285 switch runtime
.GOOS
{
287 t
.Skipf("%s does not have full support of socktest", runtime
.GOOS
)
290 origTestHookLookupIP
:= testHookLookupIP
291 defer func() { testHookLookupIP
= origTestHookLookupIP
}()
292 testHookLookupIP
= func(_ context
.Context
, fn
func(context
.Context
, string) ([]IPAddr
, error
), host
string) ([]IPAddr
, error
) {
293 return nil, &DNSError
{Err
: "listen error test", Name
: "name", Server
: "server", IsTimeout
: true}
295 sw
.Set(socktest
.FilterListen
, func(so
*socktest
.Status
) (socktest
.AfterFilter
, error
) {
296 return nil, errOpNotSupported
298 defer sw
.Set(socktest
.FilterListen
, nil)
300 for i
, tt
:= range listenErrorTests
{
301 ln
, err
:= Listen(tt
.network
, tt
.address
)
303 t
.Errorf("#%d: should fail; %s:%s->", i
, ln
.Addr().Network(), ln
.Addr())
307 if tt
.network
== "tcp" {
309 if op
, ok
:= nerr
.(*OpError
); ok
{
312 if sys
, ok
:= nerr
.(*os
.SyscallError
); ok
{
315 if nerr
== errOpNotSupported
{
316 t
.Errorf("#%d: should fail without %v; %s:%s->", i
, nerr
, tt
.network
, tt
.address
)
321 t
.Errorf("Listen returned non-nil interface %T(%v) with err != nil", ln
, ln
)
323 if err
= parseDialError(err
); err
!= nil {
324 t
.Errorf("#%d: %v", i
, err
)
330 var listenPacketErrorTests
= []struct {
331 network
, address
string
335 {"datakit", "mh/astro/r70"},
336 {"udp", "127.0.0.1:☺"},
337 {"udp", "no-such-name:80"},
338 {"udp", "mh/astro/r70:http"},
340 {"udp", JoinHostPort("127.0.0.1", "-1")},
341 {"udp", JoinHostPort("127.0.0.1", "123456789")},
344 func TestListenPacketError(t
*testing
.T
) {
345 switch runtime
.GOOS
{
347 t
.Skipf("%s does not have full support of socktest", runtime
.GOOS
)
350 origTestHookLookupIP
:= testHookLookupIP
351 defer func() { testHookLookupIP
= origTestHookLookupIP
}()
352 testHookLookupIP
= func(_ context
.Context
, fn
func(context
.Context
, string) ([]IPAddr
, error
), host
string) ([]IPAddr
, error
) {
353 return nil, &DNSError
{Err
: "listen error test", Name
: "name", Server
: "server", IsTimeout
: true}
356 for i
, tt
:= range listenPacketErrorTests
{
357 c
, err
:= ListenPacket(tt
.network
, tt
.address
)
359 t
.Errorf("#%d: should fail; %s:%s->", i
, c
.LocalAddr().Network(), c
.LocalAddr())
364 t
.Errorf("ListenPacket returned non-nil interface %T(%v) with err != nil", c
, c
)
366 if err
= parseDialError(err
); err
!= nil {
367 t
.Errorf("#%d: %v", i
, err
)
373 func TestProtocolListenError(t
*testing
.T
) {
374 switch runtime
.GOOS
{
375 case "nacl", "plan9":
376 t
.Skipf("not supported on %s", runtime
.GOOS
)
379 for _
, network
:= range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
383 _
, err
= ListenTCP(network
, &TCPAddr
{Port
: 1 << 16})
385 _
, err
= ListenUDP(network
, &UDPAddr
{Port
: 1 << 16})
386 case "ip:4294967296":
387 _
, err
= ListenIP(network
, nil)
388 case "unix", "unixpacket":
389 _
, err
= ListenUnix(network
, &UnixAddr
{Name
: "//"})
391 _
, err
= ListenUnixgram(network
, &UnixAddr
{Name
: "//"})
394 t
.Errorf("%s: should fail", network
)
397 if err
= parseDialError(err
); err
!= nil {
398 t
.Errorf("%s: %v", network
, err
)
404 // parseReadError parses nestedErr and reports whether it is a valid
405 // error value from Read functions.
406 // It returns nil when nestedErr is valid.
407 func parseReadError(nestedErr error
) error
{
408 if nestedErr
== nil {
412 switch err
:= nestedErr
.(type) {
414 if err
:= err
.isValid(); err
!= nil {
420 if nestedErr
== io
.EOF
{
423 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)
426 if isPlatformError(nestedErr
) {
429 switch err
:= nestedErr
.(type) {
430 case *os
.SyscallError
:
435 case errClosing
, errTimeout
:
438 return fmt
.Errorf("unexpected type on 2nd nested level: %T", nestedErr
)
441 if isPlatformError(nestedErr
) {
444 return fmt
.Errorf("unexpected type on 3rd nested level: %T", nestedErr
)
447 // parseWriteError parses nestedErr and reports whether it is a valid
448 // error value from Write functions.
449 // It returns nil when nestedErr is valid.
450 func parseWriteError(nestedErr error
) error
{
451 if nestedErr
== nil {
455 switch err
:= nestedErr
.(type) {
457 if err
:= err
.isValid(); err
!= nil {
463 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)
466 if isPlatformError(nestedErr
) {
469 switch err
:= nestedErr
.(type) {
470 case *AddrError
, addrinfoErrno
, *DNSError
, InvalidAddrError
, *ParseError
, *timeoutError
, UnknownNetworkError
:
472 case *os
.SyscallError
:
477 case errCanceled
, errClosing
, errMissingAddress
, errTimeout
, ErrWriteToConnected
, io
.ErrUnexpectedEOF
:
480 return fmt
.Errorf("unexpected type on 2nd nested level: %T", nestedErr
)
483 if isPlatformError(nestedErr
) {
486 return fmt
.Errorf("unexpected type on 3rd nested level: %T", nestedErr
)
489 // parseCloseError parses nestedErr and reports whether it is a valid
490 // error value from Close functions.
491 // It returns nil when nestedErr is valid.
492 func parseCloseError(nestedErr error
) error
{
493 if nestedErr
== nil {
497 switch err
:= nestedErr
.(type) {
499 if err
:= err
.isValid(); err
!= nil {
505 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)
508 if isPlatformError(nestedErr
) {
511 switch err
:= nestedErr
.(type) {
512 case *os
.SyscallError
:
515 case *os
.PathError
: // for Plan 9
523 return fmt
.Errorf("unexpected type on 2nd nested level: %T", nestedErr
)
526 if isPlatformError(nestedErr
) {
530 case os
.ErrClosed
: // for Plan 9
533 return fmt
.Errorf("unexpected type on 3rd nested level: %T", nestedErr
)
536 func TestCloseError(t
*testing
.T
) {
537 ln
, err
:= newLocalListener("tcp")
542 c
, err
:= Dial(ln
.Addr().Network(), ln
.Addr().String())
548 for i
:= 0; i
< 3; i
++ {
549 err
= c
.(*TCPConn
).CloseRead()
550 if perr
:= parseCloseError(err
); perr
!= nil {
551 t
.Errorf("#%d: %v", i
, perr
)
554 for i
:= 0; i
< 3; i
++ {
555 err
= c
.(*TCPConn
).CloseWrite()
556 if perr
:= parseCloseError(err
); perr
!= nil {
557 t
.Errorf("#%d: %v", i
, perr
)
560 for i
:= 0; i
< 3; i
++ {
562 if perr
:= parseCloseError(err
); perr
!= nil {
563 t
.Errorf("#%d: %v", i
, perr
)
566 if perr
:= parseCloseError(err
); perr
!= nil {
567 t
.Errorf("#%d: %v", i
, perr
)
571 pc
, err
:= ListenPacket("udp", "127.0.0.1:0")
577 for i
:= 0; i
< 3; i
++ {
579 if perr
:= parseCloseError(err
); perr
!= nil {
580 t
.Errorf("#%d: %v", i
, perr
)
585 // parseAcceptError parses nestedErr and reports whether it is a valid
586 // error value from Accept functions.
587 // It returns nil when nestedErr is valid.
588 func parseAcceptError(nestedErr error
) error
{
589 if nestedErr
== nil {
593 switch err
:= nestedErr
.(type) {
595 if err
:= err
.isValid(); err
!= nil {
601 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)
604 if isPlatformError(nestedErr
) {
607 switch err
:= nestedErr
.(type) {
608 case *os
.SyscallError
:
611 case *os
.PathError
: // for Plan 9
616 case errClosing
, errTimeout
:
619 return fmt
.Errorf("unexpected type on 2nd nested level: %T", nestedErr
)
622 if isPlatformError(nestedErr
) {
625 return fmt
.Errorf("unexpected type on 3rd nested level: %T", nestedErr
)
628 func TestAcceptError(t
*testing
.T
) {
629 handler
:= func(ls
*localServer
, ln Listener
) {
631 ln
.(*TCPListener
).SetDeadline(time
.Now().Add(5 * time
.Millisecond
))
632 c
, err
:= ln
.Accept()
633 if perr
:= parseAcceptError(err
); perr
!= nil {
638 t
.Errorf("Accept returned non-nil interface %T(%v) with err != nil", c
, c
)
640 if nerr
, ok
:= err
.(Error
); !ok ||
(!nerr
.Timeout() && !nerr
.Temporary()) {
648 ls
, err
:= newLocalServer("tcp")
652 if err
:= ls
.buildup(handler
); err
!= nil {
657 time
.Sleep(100 * time
.Millisecond
)
661 // parseCommonError parses nestedErr and reports whether it is a valid
662 // error value from miscellaneous functions.
663 // It returns nil when nestedErr is valid.
664 func parseCommonError(nestedErr error
) error
{
665 if nestedErr
== nil {
669 switch err
:= nestedErr
.(type) {
671 if err
:= err
.isValid(); err
!= nil {
677 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)
680 if isPlatformError(nestedErr
) {
683 switch err
:= nestedErr
.(type) {
684 case *os
.SyscallError
:
698 return fmt
.Errorf("unexpected type on 2nd nested level: %T", nestedErr
)
701 if isPlatformError(nestedErr
) {
704 return fmt
.Errorf("unexpected type on 3rd nested level: %T", nestedErr
)
707 func TestFileError(t
*testing
.T
) {
708 switch runtime
.GOOS
{
710 t
.Skipf("not supported on %s", runtime
.GOOS
)
713 f
, err
:= ioutil
.TempFile("", "go-nettest")
717 defer os
.Remove(f
.Name())
720 c
, err
:= FileConn(f
)
723 t
.Errorf("FileConn returned non-nil interface %T(%v) with err != nil", c
, c
)
725 if perr
:= parseCommonError(err
); perr
!= nil {
730 t
.Error("should fail")
732 ln
, err
:= FileListener(f
)
735 t
.Errorf("FileListener returned non-nil interface %T(%v) with err != nil", ln
, ln
)
737 if perr
:= parseCommonError(err
); perr
!= nil {
742 t
.Error("should fail")
744 pc
, err
:= FilePacketConn(f
)
747 t
.Errorf("FilePacketConn returned non-nil interface %T(%v) with err != nil", pc
, pc
)
749 if perr
:= parseCommonError(err
); perr
!= nil {
754 t
.Error("should fail")
757 ln
, err
= newLocalListener("tcp")
762 for i
:= 0; i
< 3; i
++ {
763 f
, err
:= ln
.(*TCPListener
).File()
765 if perr
:= parseCommonError(err
); perr
!= nil {
775 func parseLookupPortError(nestedErr error
) error
{
776 if nestedErr
== nil {
780 switch nestedErr
.(type) {
781 case *AddrError
, *DNSError
:
783 case *os
.PathError
: // for Plan 9
786 return fmt
.Errorf("unexpected type on 1st nested level: %T", nestedErr
)