libgo: update to Go 1.11
[official-gcc.git] / libgo / go / net / error_test.go
blobe09670e5ce0e2f8e126107bd3b95422877231696
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.
5 // +build !js
7 package net
9 import (
10 "context"
11 "fmt"
12 "internal/poll"
13 "io"
14 "io/ioutil"
15 "net/internal/socktest"
16 "os"
17 "runtime"
18 "strings"
19 "testing"
20 "time"
23 func (e *OpError) isValid() error {
24 if e.Op == "" {
25 return fmt.Errorf("OpError.Op is empty: %v", e)
27 if e.Net == "" {
28 return fmt.Errorf("OpError.Net is empty: %v", e)
30 for _, addr := range []Addr{e.Source, e.Addr} {
31 switch addr := addr.(type) {
32 case nil:
33 case *TCPAddr:
34 if addr == nil {
35 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
37 case *UDPAddr:
38 if addr == nil {
39 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
41 case *IPAddr:
42 if addr == nil {
43 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
45 case *IPNet:
46 if addr == nil {
47 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
49 case *UnixAddr:
50 if addr == nil {
51 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
53 case *pipeAddr:
54 if addr == nil {
55 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
57 case fileAddr:
58 if addr == "" {
59 return fmt.Errorf("OpError.Source or Addr is empty: %#v, %v", addr, e)
61 default:
62 return fmt.Errorf("OpError.Source or Addr is unknown type: %T, %v", addr, e)
65 if e.Err == nil {
66 return fmt.Errorf("OpError.Err is empty: %v", e)
68 return nil
71 // parseDialError parses nestedErr and reports whether it is a valid
72 // error value from Dial, Listen functions.
73 // It returns nil when nestedErr is valid.
74 func parseDialError(nestedErr error) error {
75 if nestedErr == nil {
76 return nil
79 switch err := nestedErr.(type) {
80 case *OpError:
81 if err := err.isValid(); err != nil {
82 return err
84 nestedErr = err.Err
85 goto second
87 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
89 second:
90 if isPlatformError(nestedErr) {
91 return nil
93 switch err := nestedErr.(type) {
94 case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *poll.TimeoutError, UnknownNetworkError:
95 return nil
96 case *os.SyscallError:
97 nestedErr = err.Err
98 goto third
99 case *os.PathError: // for Plan 9
100 nestedErr = err.Err
101 goto third
103 switch nestedErr {
104 case errCanceled, poll.ErrNetClosing, errMissingAddress, errNoSuitableAddress,
105 context.DeadlineExceeded, context.Canceled:
106 return nil
108 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
110 third:
111 if isPlatformError(nestedErr) {
112 return nil
114 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
117 var dialErrorTests = []struct {
118 network, address string
120 {"foo", ""},
121 {"bar", "baz"},
122 {"datakit", "mh/astro/r70"},
123 {"tcp", ""},
124 {"tcp", "127.0.0.1:☺"},
125 {"tcp", "no-such-name:80"},
126 {"tcp", "mh/astro/r70:http"},
128 {"tcp", JoinHostPort("127.0.0.1", "-1")},
129 {"tcp", JoinHostPort("127.0.0.1", "123456789")},
130 {"udp", JoinHostPort("127.0.0.1", "-1")},
131 {"udp", JoinHostPort("127.0.0.1", "123456789")},
132 {"ip:icmp", "127.0.0.1"},
134 {"unix", "/path/to/somewhere"},
135 {"unixgram", "/path/to/somewhere"},
136 {"unixpacket", "/path/to/somewhere"},
139 func TestDialError(t *testing.T) {
140 switch runtime.GOOS {
141 case "plan9":
142 t.Skipf("%s does not have full support of socktest", runtime.GOOS)
145 origTestHookLookupIP := testHookLookupIP
146 defer func() { testHookLookupIP = origTestHookLookupIP }()
147 testHookLookupIP = func(ctx context.Context, fn func(context.Context, string) ([]IPAddr, error), host string) ([]IPAddr, error) {
148 return nil, &DNSError{Err: "dial error test", Name: "name", Server: "server", IsTimeout: true}
150 sw.Set(socktest.FilterConnect, func(so *socktest.Status) (socktest.AfterFilter, error) {
151 return nil, errOpNotSupported
153 defer sw.Set(socktest.FilterConnect, nil)
155 d := Dialer{Timeout: someTimeout}
156 for i, tt := range dialErrorTests {
157 c, err := d.Dial(tt.network, tt.address)
158 if err == nil {
159 t.Errorf("#%d: should fail; %s:%s->%s", i, c.LocalAddr().Network(), c.LocalAddr(), c.RemoteAddr())
160 c.Close()
161 continue
163 if tt.network == "tcp" || tt.network == "udp" {
164 nerr := err
165 if op, ok := nerr.(*OpError); ok {
166 nerr = op.Err
168 if sys, ok := nerr.(*os.SyscallError); ok {
169 nerr = sys.Err
171 if nerr == errOpNotSupported {
172 t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
173 continue
176 if c != nil {
177 t.Errorf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
179 if err = parseDialError(err); err != nil {
180 t.Errorf("#%d: %v", i, err)
181 continue
186 func TestProtocolDialError(t *testing.T) {
187 switch runtime.GOOS {
188 case "nacl", "solaris":
189 t.Skipf("not supported on %s", runtime.GOOS)
192 for _, network := range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
193 var err error
194 switch network {
195 case "tcp":
196 _, err = DialTCP(network, nil, &TCPAddr{Port: 1 << 16})
197 case "udp":
198 _, err = DialUDP(network, nil, &UDPAddr{Port: 1 << 16})
199 case "ip:4294967296":
200 _, err = DialIP(network, nil, nil)
201 case "unix", "unixpacket", "unixgram":
202 _, err = DialUnix(network, nil, &UnixAddr{Name: "//"})
204 if err == nil {
205 t.Errorf("%s: should fail", network)
206 continue
208 if err = parseDialError(err); err != nil {
209 t.Errorf("%s: %v", network, err)
210 continue
215 func TestDialAddrError(t *testing.T) {
216 switch runtime.GOOS {
217 case "nacl", "plan9":
218 t.Skipf("not supported on %s", runtime.GOOS)
220 if !supportsIPv4() || !supportsIPv6() {
221 t.Skip("both IPv4 and IPv6 are required")
224 for _, tt := range []struct {
225 network string
226 lit string
227 addr *TCPAddr
229 {"tcp4", "::1", nil},
230 {"tcp4", "", &TCPAddr{IP: IPv6loopback}},
231 // We don't test the {"tcp6", "byte sequence", nil}
232 // case for now because there is no easy way to
233 // control name resolution.
234 {"tcp6", "", &TCPAddr{IP: IP{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}}},
236 var err error
237 var c Conn
238 var op string
239 if tt.lit != "" {
240 c, err = Dial(tt.network, JoinHostPort(tt.lit, "0"))
241 op = fmt.Sprintf("Dial(%q, %q)", tt.network, JoinHostPort(tt.lit, "0"))
242 } else {
243 c, err = DialTCP(tt.network, nil, tt.addr)
244 op = fmt.Sprintf("DialTCP(%q, %q)", tt.network, tt.addr)
246 if err == nil {
247 c.Close()
248 t.Errorf("%s succeeded, want error", op)
249 continue
251 if perr := parseDialError(err); perr != nil {
252 t.Errorf("%s: %v", op, perr)
253 continue
255 operr := err.(*OpError).Err
256 aerr, ok := operr.(*AddrError)
257 if !ok {
258 t.Errorf("%s: %v is %T, want *AddrError", op, err, operr)
259 continue
261 want := tt.lit
262 if tt.lit == "" {
263 want = tt.addr.IP.String()
265 if aerr.Addr != want {
266 t.Errorf("%s: %v, error Addr=%q, want %q", op, err, aerr.Addr, want)
271 var listenErrorTests = []struct {
272 network, address string
274 {"foo", ""},
275 {"bar", "baz"},
276 {"datakit", "mh/astro/r70"},
277 {"tcp", "127.0.0.1:☺"},
278 {"tcp", "no-such-name:80"},
279 {"tcp", "mh/astro/r70:http"},
281 {"tcp", JoinHostPort("127.0.0.1", "-1")},
282 {"tcp", JoinHostPort("127.0.0.1", "123456789")},
284 {"unix", "/path/to/somewhere"},
285 {"unixpacket", "/path/to/somewhere"},
288 func TestListenError(t *testing.T) {
289 switch runtime.GOOS {
290 case "plan9":
291 t.Skipf("%s does not have full support of socktest", runtime.GOOS)
294 origTestHookLookupIP := testHookLookupIP
295 defer func() { testHookLookupIP = origTestHookLookupIP }()
296 testHookLookupIP = func(_ context.Context, fn func(context.Context, string) ([]IPAddr, error), host string) ([]IPAddr, error) {
297 return nil, &DNSError{Err: "listen error test", Name: "name", Server: "server", IsTimeout: true}
299 sw.Set(socktest.FilterListen, func(so *socktest.Status) (socktest.AfterFilter, error) {
300 return nil, errOpNotSupported
302 defer sw.Set(socktest.FilterListen, nil)
304 for i, tt := range listenErrorTests {
305 ln, err := Listen(tt.network, tt.address)
306 if err == nil {
307 t.Errorf("#%d: should fail; %s:%s->", i, ln.Addr().Network(), ln.Addr())
308 ln.Close()
309 continue
311 if tt.network == "tcp" {
312 nerr := err
313 if op, ok := nerr.(*OpError); ok {
314 nerr = op.Err
316 if sys, ok := nerr.(*os.SyscallError); ok {
317 nerr = sys.Err
319 if nerr == errOpNotSupported {
320 t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
321 continue
324 if ln != nil {
325 t.Errorf("Listen returned non-nil interface %T(%v) with err != nil", ln, ln)
327 if err = parseDialError(err); err != nil {
328 t.Errorf("#%d: %v", i, err)
329 continue
334 var listenPacketErrorTests = []struct {
335 network, address string
337 {"foo", ""},
338 {"bar", "baz"},
339 {"datakit", "mh/astro/r70"},
340 {"udp", "127.0.0.1:☺"},
341 {"udp", "no-such-name:80"},
342 {"udp", "mh/astro/r70:http"},
344 {"udp", JoinHostPort("127.0.0.1", "-1")},
345 {"udp", JoinHostPort("127.0.0.1", "123456789")},
348 func TestListenPacketError(t *testing.T) {
349 switch runtime.GOOS {
350 case "plan9":
351 t.Skipf("%s does not have full support of socktest", runtime.GOOS)
354 origTestHookLookupIP := testHookLookupIP
355 defer func() { testHookLookupIP = origTestHookLookupIP }()
356 testHookLookupIP = func(_ context.Context, fn func(context.Context, string) ([]IPAddr, error), host string) ([]IPAddr, error) {
357 return nil, &DNSError{Err: "listen error test", Name: "name", Server: "server", IsTimeout: true}
360 for i, tt := range listenPacketErrorTests {
361 c, err := ListenPacket(tt.network, tt.address)
362 if err == nil {
363 t.Errorf("#%d: should fail; %s:%s->", i, c.LocalAddr().Network(), c.LocalAddr())
364 c.Close()
365 continue
367 if c != nil {
368 t.Errorf("ListenPacket returned non-nil interface %T(%v) with err != nil", c, c)
370 if err = parseDialError(err); err != nil {
371 t.Errorf("#%d: %v", i, err)
372 continue
377 func TestProtocolListenError(t *testing.T) {
378 switch runtime.GOOS {
379 case "nacl", "plan9":
380 t.Skipf("not supported on %s", runtime.GOOS)
383 for _, network := range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
384 var err error
385 switch network {
386 case "tcp":
387 _, err = ListenTCP(network, &TCPAddr{Port: 1 << 16})
388 case "udp":
389 _, err = ListenUDP(network, &UDPAddr{Port: 1 << 16})
390 case "ip:4294967296":
391 _, err = ListenIP(network, nil)
392 case "unix", "unixpacket":
393 _, err = ListenUnix(network, &UnixAddr{Name: "//"})
394 case "unixgram":
395 _, err = ListenUnixgram(network, &UnixAddr{Name: "//"})
397 if err == nil {
398 t.Errorf("%s: should fail", network)
399 continue
401 if err = parseDialError(err); err != nil {
402 t.Errorf("%s: %v", network, err)
403 continue
408 // parseReadError parses nestedErr and reports whether it is a valid
409 // error value from Read functions.
410 // It returns nil when nestedErr is valid.
411 func parseReadError(nestedErr error) error {
412 if nestedErr == nil {
413 return nil
416 switch err := nestedErr.(type) {
417 case *OpError:
418 if err := err.isValid(); err != nil {
419 return err
421 nestedErr = err.Err
422 goto second
424 if nestedErr == io.EOF {
425 return nil
427 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
429 second:
430 if isPlatformError(nestedErr) {
431 return nil
433 switch err := nestedErr.(type) {
434 case *os.SyscallError:
435 nestedErr = err.Err
436 goto third
438 switch nestedErr {
439 case poll.ErrNetClosing, poll.ErrTimeout:
440 return nil
442 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
444 third:
445 if isPlatformError(nestedErr) {
446 return nil
448 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
451 // parseWriteError parses nestedErr and reports whether it is a valid
452 // error value from Write functions.
453 // It returns nil when nestedErr is valid.
454 func parseWriteError(nestedErr error) error {
455 if nestedErr == nil {
456 return nil
459 switch err := nestedErr.(type) {
460 case *OpError:
461 if err := err.isValid(); err != nil {
462 return err
464 nestedErr = err.Err
465 goto second
467 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
469 second:
470 if isPlatformError(nestedErr) {
471 return nil
473 switch err := nestedErr.(type) {
474 case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *poll.TimeoutError, UnknownNetworkError:
475 return nil
476 case *os.SyscallError:
477 nestedErr = err.Err
478 goto third
480 switch nestedErr {
481 case errCanceled, poll.ErrNetClosing, errMissingAddress, poll.ErrTimeout, ErrWriteToConnected, io.ErrUnexpectedEOF:
482 return nil
484 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
486 third:
487 if isPlatformError(nestedErr) {
488 return nil
490 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
493 // parseCloseError parses nestedErr and reports whether it is a valid
494 // error value from Close functions.
495 // It returns nil when nestedErr is valid.
496 func parseCloseError(nestedErr error, isShutdown bool) error {
497 if nestedErr == nil {
498 return nil
501 // Because historically we have not exported the error that we
502 // return for an operation on a closed network connection,
503 // there are programs that test for the exact error string.
504 // Verify that string here so that we don't break those
505 // programs unexpectedly. See issues #4373 and #19252.
506 want := "use of closed network connection"
507 if !isShutdown && !strings.Contains(nestedErr.Error(), want) {
508 return fmt.Errorf("error string %q does not contain expected string %q", nestedErr, want)
511 switch err := nestedErr.(type) {
512 case *OpError:
513 if err := err.isValid(); err != nil {
514 return err
516 nestedErr = err.Err
517 goto second
519 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
521 second:
522 if isPlatformError(nestedErr) {
523 return nil
525 switch err := nestedErr.(type) {
526 case *os.SyscallError:
527 nestedErr = err.Err
528 goto third
529 case *os.PathError: // for Plan 9
530 nestedErr = err.Err
531 goto third
533 switch nestedErr {
534 case poll.ErrNetClosing:
535 return nil
537 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
539 third:
540 if isPlatformError(nestedErr) {
541 return nil
543 switch nestedErr {
544 case os.ErrClosed: // for Plan 9
545 return nil
547 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
550 func TestCloseError(t *testing.T) {
551 ln, err := newLocalListener("tcp")
552 if err != nil {
553 t.Fatal(err)
555 defer ln.Close()
556 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
557 if err != nil {
558 t.Fatal(err)
560 defer c.Close()
562 for i := 0; i < 3; i++ {
563 err = c.(*TCPConn).CloseRead()
564 if perr := parseCloseError(err, true); perr != nil {
565 t.Errorf("#%d: %v", i, perr)
568 for i := 0; i < 3; i++ {
569 err = c.(*TCPConn).CloseWrite()
570 if perr := parseCloseError(err, true); perr != nil {
571 t.Errorf("#%d: %v", i, perr)
574 for i := 0; i < 3; i++ {
575 err = c.Close()
576 if perr := parseCloseError(err, false); perr != nil {
577 t.Errorf("#%d: %v", i, perr)
579 err = ln.Close()
580 if perr := parseCloseError(err, false); perr != nil {
581 t.Errorf("#%d: %v", i, perr)
585 pc, err := ListenPacket("udp", "127.0.0.1:0")
586 if err != nil {
587 t.Fatal(err)
589 defer pc.Close()
591 for i := 0; i < 3; i++ {
592 err = pc.Close()
593 if perr := parseCloseError(err, false); perr != nil {
594 t.Errorf("#%d: %v", i, perr)
599 // parseAcceptError parses nestedErr and reports whether it is a valid
600 // error value from Accept functions.
601 // It returns nil when nestedErr is valid.
602 func parseAcceptError(nestedErr error) error {
603 if nestedErr == nil {
604 return nil
607 switch err := nestedErr.(type) {
608 case *OpError:
609 if err := err.isValid(); err != nil {
610 return err
612 nestedErr = err.Err
613 goto second
615 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
617 second:
618 if isPlatformError(nestedErr) {
619 return nil
621 switch err := nestedErr.(type) {
622 case *os.SyscallError:
623 nestedErr = err.Err
624 goto third
625 case *os.PathError: // for Plan 9
626 nestedErr = err.Err
627 goto third
629 switch nestedErr {
630 case poll.ErrNetClosing, poll.ErrTimeout:
631 return nil
633 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
635 third:
636 if isPlatformError(nestedErr) {
637 return nil
639 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
642 func TestAcceptError(t *testing.T) {
643 handler := func(ls *localServer, ln Listener) {
644 for {
645 ln.(*TCPListener).SetDeadline(time.Now().Add(5 * time.Millisecond))
646 c, err := ln.Accept()
647 if perr := parseAcceptError(err); perr != nil {
648 t.Error(perr)
650 if err != nil {
651 if c != nil {
652 t.Errorf("Accept returned non-nil interface %T(%v) with err != nil", c, c)
654 if nerr, ok := err.(Error); !ok || (!nerr.Timeout() && !nerr.Temporary()) {
655 return
657 continue
659 c.Close()
662 ls, err := newLocalServer("tcp")
663 if err != nil {
664 t.Fatal(err)
666 if err := ls.buildup(handler); err != nil {
667 ls.teardown()
668 t.Fatal(err)
671 time.Sleep(100 * time.Millisecond)
672 ls.teardown()
675 // parseCommonError parses nestedErr and reports whether it is a valid
676 // error value from miscellaneous functions.
677 // It returns nil when nestedErr is valid.
678 func parseCommonError(nestedErr error) error {
679 if nestedErr == nil {
680 return nil
683 switch err := nestedErr.(type) {
684 case *OpError:
685 if err := err.isValid(); err != nil {
686 return err
688 nestedErr = err.Err
689 goto second
691 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
693 second:
694 if isPlatformError(nestedErr) {
695 return nil
697 switch err := nestedErr.(type) {
698 case *os.SyscallError:
699 nestedErr = err.Err
700 goto third
701 case *os.LinkError:
702 nestedErr = err.Err
703 goto third
704 case *os.PathError:
705 nestedErr = err.Err
706 goto third
708 switch nestedErr {
709 case poll.ErrNetClosing:
710 return nil
712 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
714 third:
715 if isPlatformError(nestedErr) {
716 return nil
718 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
721 func TestFileError(t *testing.T) {
722 switch runtime.GOOS {
723 case "windows":
724 t.Skipf("not supported on %s", runtime.GOOS)
727 f, err := ioutil.TempFile("", "go-nettest")
728 if err != nil {
729 t.Fatal(err)
731 defer os.Remove(f.Name())
732 defer f.Close()
734 c, err := FileConn(f)
735 if err != nil {
736 if c != nil {
737 t.Errorf("FileConn returned non-nil interface %T(%v) with err != nil", c, c)
739 if perr := parseCommonError(err); perr != nil {
740 t.Error(perr)
742 } else {
743 c.Close()
744 t.Error("should fail")
746 ln, err := FileListener(f)
747 if err != nil {
748 if ln != nil {
749 t.Errorf("FileListener returned non-nil interface %T(%v) with err != nil", ln, ln)
751 if perr := parseCommonError(err); perr != nil {
752 t.Error(perr)
754 } else {
755 ln.Close()
756 t.Error("should fail")
758 pc, err := FilePacketConn(f)
759 if err != nil {
760 if pc != nil {
761 t.Errorf("FilePacketConn returned non-nil interface %T(%v) with err != nil", pc, pc)
763 if perr := parseCommonError(err); perr != nil {
764 t.Error(perr)
766 } else {
767 pc.Close()
768 t.Error("should fail")
771 ln, err = newLocalListener("tcp")
772 if err != nil {
773 t.Fatal(err)
776 for i := 0; i < 3; i++ {
777 f, err := ln.(*TCPListener).File()
778 if err != nil {
779 if perr := parseCommonError(err); perr != nil {
780 t.Error(perr)
782 } else {
783 f.Close()
785 ln.Close()
789 func parseLookupPortError(nestedErr error) error {
790 if nestedErr == nil {
791 return nil
794 switch nestedErr.(type) {
795 case *AddrError, *DNSError:
796 return nil
797 case *os.PathError: // for Plan 9
798 return nil
800 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)