PR tree-optimization/84480 - bogus -Wstringop-truncation despite assignment with...
[official-gcc.git] / libgo / go / net / error_test.go
blob9791e6fe4defb61e86367e43e05fb1d923329be2
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 package net
7 import (
8 "context"
9 "fmt"
10 "internal/poll"
11 "io"
12 "io/ioutil"
13 "net/internal/socktest"
14 "os"
15 "runtime"
16 "strings"
17 "testing"
18 "time"
21 func (e *OpError) isValid() error {
22 if e.Op == "" {
23 return fmt.Errorf("OpError.Op is empty: %v", e)
25 if e.Net == "" {
26 return fmt.Errorf("OpError.Net is empty: %v", e)
28 for _, addr := range []Addr{e.Source, e.Addr} {
29 switch addr := addr.(type) {
30 case nil:
31 case *TCPAddr:
32 if addr == nil {
33 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
35 case *UDPAddr:
36 if addr == nil {
37 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
39 case *IPAddr:
40 if addr == nil {
41 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
43 case *IPNet:
44 if addr == nil {
45 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
47 case *UnixAddr:
48 if addr == nil {
49 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
51 case *pipeAddr:
52 if addr == nil {
53 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
55 case fileAddr:
56 if addr == "" {
57 return fmt.Errorf("OpError.Source or Addr is empty: %#v, %v", addr, e)
59 default:
60 return fmt.Errorf("OpError.Source or Addr is unknown type: %T, %v", addr, e)
63 if e.Err == nil {
64 return fmt.Errorf("OpError.Err is empty: %v", e)
66 return nil
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 {
73 if nestedErr == nil {
74 return nil
77 switch err := nestedErr.(type) {
78 case *OpError:
79 if err := err.isValid(); err != nil {
80 return err
82 nestedErr = err.Err
83 goto second
85 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
87 second:
88 if isPlatformError(nestedErr) {
89 return nil
91 switch err := nestedErr.(type) {
92 case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *poll.TimeoutError, UnknownNetworkError:
93 return nil
94 case *os.SyscallError:
95 nestedErr = err.Err
96 goto third
97 case *os.PathError: // for Plan 9
98 nestedErr = err.Err
99 goto third
101 switch nestedErr {
102 case errCanceled, poll.ErrNetClosing, errMissingAddress, errNoSuitableAddress,
103 context.DeadlineExceeded, context.Canceled:
104 return nil
106 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
108 third:
109 if isPlatformError(nestedErr) {
110 return nil
112 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
115 var dialErrorTests = []struct {
116 network, address string
118 {"foo", ""},
119 {"bar", "baz"},
120 {"datakit", "mh/astro/r70"},
121 {"tcp", ""},
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 {
139 case "plan9":
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)
156 if err == nil {
157 t.Errorf("#%d: should fail; %s:%s->%s", i, c.LocalAddr().Network(), c.LocalAddr(), c.RemoteAddr())
158 c.Close()
159 continue
161 if tt.network == "tcp" || tt.network == "udp" {
162 nerr := err
163 if op, ok := nerr.(*OpError); ok {
164 nerr = op.Err
166 if sys, ok := nerr.(*os.SyscallError); ok {
167 nerr = sys.Err
169 if nerr == errOpNotSupported {
170 t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
171 continue
174 if c != nil {
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)
179 continue
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"} {
191 var err error
192 switch network {
193 case "tcp":
194 _, err = DialTCP(network, nil, &TCPAddr{Port: 1 << 16})
195 case "udp":
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: "//"})
202 if err == nil {
203 t.Errorf("%s: should fail", network)
204 continue
206 if err = parseDialError(err); err != nil {
207 t.Errorf("%s: %v", network, err)
208 continue
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 {
223 network string
224 lit string
225 addr *TCPAddr
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}}},
234 var err error
235 var c Conn
236 var op string
237 if tt.lit != "" {
238 c, err = Dial(tt.network, JoinHostPort(tt.lit, "0"))
239 op = fmt.Sprintf("Dial(%q, %q)", tt.network, JoinHostPort(tt.lit, "0"))
240 } else {
241 c, err = DialTCP(tt.network, nil, tt.addr)
242 op = fmt.Sprintf("DialTCP(%q, %q)", tt.network, tt.addr)
244 if err == nil {
245 c.Close()
246 t.Errorf("%s succeeded, want error", op)
247 continue
249 if perr := parseDialError(err); perr != nil {
250 t.Errorf("%s: %v", op, perr)
251 continue
253 operr := err.(*OpError).Err
254 aerr, ok := operr.(*AddrError)
255 if !ok {
256 t.Errorf("%s: %v is %T, want *AddrError", op, err, operr)
257 continue
259 want := tt.lit
260 if tt.lit == "" {
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
272 {"foo", ""},
273 {"bar", "baz"},
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 {
288 case "plan9":
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)
304 if err == nil {
305 t.Errorf("#%d: should fail; %s:%s->", i, ln.Addr().Network(), ln.Addr())
306 ln.Close()
307 continue
309 if tt.network == "tcp" {
310 nerr := err
311 if op, ok := nerr.(*OpError); ok {
312 nerr = op.Err
314 if sys, ok := nerr.(*os.SyscallError); ok {
315 nerr = sys.Err
317 if nerr == errOpNotSupported {
318 t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
319 continue
322 if ln != nil {
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)
327 continue
332 var listenPacketErrorTests = []struct {
333 network, address string
335 {"foo", ""},
336 {"bar", "baz"},
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 {
348 case "plan9":
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)
360 if err == nil {
361 t.Errorf("#%d: should fail; %s:%s->", i, c.LocalAddr().Network(), c.LocalAddr())
362 c.Close()
363 continue
365 if c != nil {
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)
370 continue
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"} {
382 var err error
383 switch network {
384 case "tcp":
385 _, err = ListenTCP(network, &TCPAddr{Port: 1 << 16})
386 case "udp":
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: "//"})
392 case "unixgram":
393 _, err = ListenUnixgram(network, &UnixAddr{Name: "//"})
395 if err == nil {
396 t.Errorf("%s: should fail", network)
397 continue
399 if err = parseDialError(err); err != nil {
400 t.Errorf("%s: %v", network, err)
401 continue
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 {
411 return nil
414 switch err := nestedErr.(type) {
415 case *OpError:
416 if err := err.isValid(); err != nil {
417 return err
419 nestedErr = err.Err
420 goto second
422 if nestedErr == io.EOF {
423 return nil
425 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
427 second:
428 if isPlatformError(nestedErr) {
429 return nil
431 switch err := nestedErr.(type) {
432 case *os.SyscallError:
433 nestedErr = err.Err
434 goto third
436 switch nestedErr {
437 case poll.ErrNetClosing, poll.ErrTimeout:
438 return nil
440 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
442 third:
443 if isPlatformError(nestedErr) {
444 return nil
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 {
454 return nil
457 switch err := nestedErr.(type) {
458 case *OpError:
459 if err := err.isValid(); err != nil {
460 return err
462 nestedErr = err.Err
463 goto second
465 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
467 second:
468 if isPlatformError(nestedErr) {
469 return nil
471 switch err := nestedErr.(type) {
472 case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *poll.TimeoutError, UnknownNetworkError:
473 return nil
474 case *os.SyscallError:
475 nestedErr = err.Err
476 goto third
478 switch nestedErr {
479 case errCanceled, poll.ErrNetClosing, errMissingAddress, poll.ErrTimeout, ErrWriteToConnected, io.ErrUnexpectedEOF:
480 return nil
482 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
484 third:
485 if isPlatformError(nestedErr) {
486 return nil
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 {
496 return 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) {
510 case *OpError:
511 if err := err.isValid(); err != nil {
512 return err
514 nestedErr = err.Err
515 goto second
517 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
519 second:
520 if isPlatformError(nestedErr) {
521 return nil
523 switch err := nestedErr.(type) {
524 case *os.SyscallError:
525 nestedErr = err.Err
526 goto third
527 case *os.PathError: // for Plan 9
528 nestedErr = err.Err
529 goto third
531 switch nestedErr {
532 case poll.ErrNetClosing:
533 return nil
535 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
537 third:
538 if isPlatformError(nestedErr) {
539 return nil
541 switch nestedErr {
542 case os.ErrClosed: // for Plan 9
543 return nil
545 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
548 func TestCloseError(t *testing.T) {
549 ln, err := newLocalListener("tcp")
550 if err != nil {
551 t.Fatal(err)
553 defer ln.Close()
554 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
555 if err != nil {
556 t.Fatal(err)
558 defer c.Close()
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++ {
573 err = c.Close()
574 if perr := parseCloseError(err, false); perr != nil {
575 t.Errorf("#%d: %v", i, perr)
577 err = ln.Close()
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")
584 if err != nil {
585 t.Fatal(err)
587 defer pc.Close()
589 for i := 0; i < 3; i++ {
590 err = pc.Close()
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 {
602 return nil
605 switch err := nestedErr.(type) {
606 case *OpError:
607 if err := err.isValid(); err != nil {
608 return err
610 nestedErr = err.Err
611 goto second
613 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
615 second:
616 if isPlatformError(nestedErr) {
617 return nil
619 switch err := nestedErr.(type) {
620 case *os.SyscallError:
621 nestedErr = err.Err
622 goto third
623 case *os.PathError: // for Plan 9
624 nestedErr = err.Err
625 goto third
627 switch nestedErr {
628 case poll.ErrNetClosing, poll.ErrTimeout:
629 return nil
631 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
633 third:
634 if isPlatformError(nestedErr) {
635 return nil
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) {
642 for {
643 ln.(*TCPListener).SetDeadline(time.Now().Add(5 * time.Millisecond))
644 c, err := ln.Accept()
645 if perr := parseAcceptError(err); perr != nil {
646 t.Error(perr)
648 if err != nil {
649 if c != 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()) {
653 return
655 continue
657 c.Close()
660 ls, err := newLocalServer("tcp")
661 if err != nil {
662 t.Fatal(err)
664 if err := ls.buildup(handler); err != nil {
665 ls.teardown()
666 t.Fatal(err)
669 time.Sleep(100 * time.Millisecond)
670 ls.teardown()
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 {
678 return nil
681 switch err := nestedErr.(type) {
682 case *OpError:
683 if err := err.isValid(); err != nil {
684 return err
686 nestedErr = err.Err
687 goto second
689 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
691 second:
692 if isPlatformError(nestedErr) {
693 return nil
695 switch err := nestedErr.(type) {
696 case *os.SyscallError:
697 nestedErr = err.Err
698 goto third
699 case *os.LinkError:
700 nestedErr = err.Err
701 goto third
702 case *os.PathError:
703 nestedErr = err.Err
704 goto third
706 switch nestedErr {
707 case poll.ErrNetClosing:
708 return nil
710 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
712 third:
713 if isPlatformError(nestedErr) {
714 return nil
716 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
719 func TestFileError(t *testing.T) {
720 switch runtime.GOOS {
721 case "windows":
722 t.Skipf("not supported on %s", runtime.GOOS)
725 f, err := ioutil.TempFile("", "go-nettest")
726 if err != nil {
727 t.Fatal(err)
729 defer os.Remove(f.Name())
730 defer f.Close()
732 c, err := FileConn(f)
733 if err != nil {
734 if c != nil {
735 t.Errorf("FileConn returned non-nil interface %T(%v) with err != nil", c, c)
737 if perr := parseCommonError(err); perr != nil {
738 t.Error(perr)
740 } else {
741 c.Close()
742 t.Error("should fail")
744 ln, err := FileListener(f)
745 if err != nil {
746 if ln != nil {
747 t.Errorf("FileListener returned non-nil interface %T(%v) with err != nil", ln, ln)
749 if perr := parseCommonError(err); perr != nil {
750 t.Error(perr)
752 } else {
753 ln.Close()
754 t.Error("should fail")
756 pc, err := FilePacketConn(f)
757 if err != nil {
758 if pc != nil {
759 t.Errorf("FilePacketConn returned non-nil interface %T(%v) with err != nil", pc, pc)
761 if perr := parseCommonError(err); perr != nil {
762 t.Error(perr)
764 } else {
765 pc.Close()
766 t.Error("should fail")
769 ln, err = newLocalListener("tcp")
770 if err != nil {
771 t.Fatal(err)
774 for i := 0; i < 3; i++ {
775 f, err := ln.(*TCPListener).File()
776 if err != nil {
777 if perr := parseCommonError(err); perr != nil {
778 t.Error(perr)
780 } else {
781 f.Close()
783 ln.Close()
787 func parseLookupPortError(nestedErr error) error {
788 if nestedErr == nil {
789 return nil
792 switch nestedErr.(type) {
793 case *AddrError, *DNSError:
794 return nil
795 case *os.PathError: // for Plan 9
796 return nil
798 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)