2017-03-02 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgo / go / net / error_test.go
blobc23da49fad91289da0ccea8dcc2cd344427decf0
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 "io"
11 "io/ioutil"
12 "net/internal/socktest"
13 "os"
14 "runtime"
15 "testing"
16 "time"
19 func (e *OpError) isValid() error {
20 if e.Op == "" {
21 return fmt.Errorf("OpError.Op is empty: %v", e)
23 if e.Net == "" {
24 return fmt.Errorf("OpError.Net is empty: %v", e)
26 for _, addr := range []Addr{e.Source, e.Addr} {
27 switch addr := addr.(type) {
28 case nil:
29 case *TCPAddr:
30 if addr == nil {
31 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
33 case *UDPAddr:
34 if addr == nil {
35 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
37 case *IPAddr:
38 if addr == nil {
39 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
41 case *IPNet:
42 if addr == nil {
43 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
45 case *UnixAddr:
46 if addr == nil {
47 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
49 case *pipeAddr:
50 if addr == nil {
51 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
53 case fileAddr:
54 if addr == "" {
55 return fmt.Errorf("OpError.Source or Addr is empty: %#v, %v", addr, e)
57 default:
58 return fmt.Errorf("OpError.Source or Addr is unknown type: %T, %v", addr, e)
61 if e.Err == nil {
62 return fmt.Errorf("OpError.Err is empty: %v", e)
64 return nil
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 {
71 if nestedErr == nil {
72 return nil
75 switch err := nestedErr.(type) {
76 case *OpError:
77 if err := err.isValid(); err != nil {
78 return err
80 nestedErr = err.Err
81 goto second
83 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
85 second:
86 if isPlatformError(nestedErr) {
87 return nil
89 switch err := nestedErr.(type) {
90 case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *timeoutError, UnknownNetworkError:
91 return nil
92 case *os.SyscallError:
93 nestedErr = err.Err
94 goto third
95 case *os.PathError: // for Plan 9
96 nestedErr = err.Err
97 goto third
99 switch nestedErr {
100 case errCanceled, errClosing, errMissingAddress, errNoSuitableAddress,
101 context.DeadlineExceeded, context.Canceled:
102 return nil
104 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
106 third:
107 if isPlatformError(nestedErr) {
108 return nil
110 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
113 var dialErrorTests = []struct {
114 network, address string
116 {"foo", ""},
117 {"bar", "baz"},
118 {"datakit", "mh/astro/r70"},
119 {"tcp", ""},
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 {
137 case "plan9":
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)
154 if err == nil {
155 t.Errorf("#%d: should fail; %s:%s->%s", i, c.LocalAddr().Network(), c.LocalAddr(), c.RemoteAddr())
156 c.Close()
157 continue
159 if tt.network == "tcp" || tt.network == "udp" {
160 nerr := err
161 if op, ok := nerr.(*OpError); ok {
162 nerr = op.Err
164 if sys, ok := nerr.(*os.SyscallError); ok {
165 nerr = sys.Err
167 if nerr == errOpNotSupported {
168 t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
169 continue
172 if c != nil {
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)
177 continue
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"} {
189 var err error
190 switch network {
191 case "tcp":
192 _, err = DialTCP(network, nil, &TCPAddr{Port: 1 << 16})
193 case "udp":
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: "//"})
200 if err == nil {
201 t.Errorf("%s: should fail", network)
202 continue
204 if err = parseDialError(err); err != nil {
205 t.Errorf("%s: %v", network, err)
206 continue
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 {
221 network string
222 lit string
223 addr *TCPAddr
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}}},
232 var err error
233 var c Conn
234 var op string
235 if tt.lit != "" {
236 c, err = Dial(tt.network, JoinHostPort(tt.lit, "0"))
237 op = fmt.Sprintf("Dial(%q, %q)", tt.network, JoinHostPort(tt.lit, "0"))
238 } else {
239 c, err = DialTCP(tt.network, nil, tt.addr)
240 op = fmt.Sprintf("DialTCP(%q, %q)", tt.network, tt.addr)
242 if err == nil {
243 c.Close()
244 t.Errorf("%s succeeded, want error", op)
245 continue
247 if perr := parseDialError(err); perr != nil {
248 t.Errorf("%s: %v", op, perr)
249 continue
251 operr := err.(*OpError).Err
252 aerr, ok := operr.(*AddrError)
253 if !ok {
254 t.Errorf("%s: %v is %T, want *AddrError", op, err, operr)
255 continue
257 want := tt.lit
258 if tt.lit == "" {
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
270 {"foo", ""},
271 {"bar", "baz"},
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 {
286 case "plan9":
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)
302 if err == nil {
303 t.Errorf("#%d: should fail; %s:%s->", i, ln.Addr().Network(), ln.Addr())
304 ln.Close()
305 continue
307 if tt.network == "tcp" {
308 nerr := err
309 if op, ok := nerr.(*OpError); ok {
310 nerr = op.Err
312 if sys, ok := nerr.(*os.SyscallError); ok {
313 nerr = sys.Err
315 if nerr == errOpNotSupported {
316 t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
317 continue
320 if ln != nil {
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)
325 continue
330 var listenPacketErrorTests = []struct {
331 network, address string
333 {"foo", ""},
334 {"bar", "baz"},
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 {
346 case "plan9":
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)
358 if err == nil {
359 t.Errorf("#%d: should fail; %s:%s->", i, c.LocalAddr().Network(), c.LocalAddr())
360 c.Close()
361 continue
363 if c != nil {
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)
368 continue
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"} {
380 var err error
381 switch network {
382 case "tcp":
383 _, err = ListenTCP(network, &TCPAddr{Port: 1 << 16})
384 case "udp":
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: "//"})
390 case "unixgram":
391 _, err = ListenUnixgram(network, &UnixAddr{Name: "//"})
393 if err == nil {
394 t.Errorf("%s: should fail", network)
395 continue
397 if err = parseDialError(err); err != nil {
398 t.Errorf("%s: %v", network, err)
399 continue
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 {
409 return nil
412 switch err := nestedErr.(type) {
413 case *OpError:
414 if err := err.isValid(); err != nil {
415 return err
417 nestedErr = err.Err
418 goto second
420 if nestedErr == io.EOF {
421 return nil
423 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
425 second:
426 if isPlatformError(nestedErr) {
427 return nil
429 switch err := nestedErr.(type) {
430 case *os.SyscallError:
431 nestedErr = err.Err
432 goto third
434 switch nestedErr {
435 case errClosing, errTimeout:
436 return nil
438 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
440 third:
441 if isPlatformError(nestedErr) {
442 return nil
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 {
452 return nil
455 switch err := nestedErr.(type) {
456 case *OpError:
457 if err := err.isValid(); err != nil {
458 return err
460 nestedErr = err.Err
461 goto second
463 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
465 second:
466 if isPlatformError(nestedErr) {
467 return nil
469 switch err := nestedErr.(type) {
470 case *AddrError, addrinfoErrno, *DNSError, InvalidAddrError, *ParseError, *timeoutError, UnknownNetworkError:
471 return nil
472 case *os.SyscallError:
473 nestedErr = err.Err
474 goto third
476 switch nestedErr {
477 case errCanceled, errClosing, errMissingAddress, errTimeout, ErrWriteToConnected, io.ErrUnexpectedEOF:
478 return nil
480 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
482 third:
483 if isPlatformError(nestedErr) {
484 return nil
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 {
494 return nil
497 switch err := nestedErr.(type) {
498 case *OpError:
499 if err := err.isValid(); err != nil {
500 return err
502 nestedErr = err.Err
503 goto second
505 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
507 second:
508 if isPlatformError(nestedErr) {
509 return nil
511 switch err := nestedErr.(type) {
512 case *os.SyscallError:
513 nestedErr = err.Err
514 goto third
515 case *os.PathError: // for Plan 9
516 nestedErr = err.Err
517 goto third
519 switch nestedErr {
520 case errClosing:
521 return nil
523 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
525 third:
526 if isPlatformError(nestedErr) {
527 return nil
529 switch nestedErr {
530 case os.ErrClosed: // for Plan 9
531 return nil
533 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
536 func TestCloseError(t *testing.T) {
537 ln, err := newLocalListener("tcp")
538 if err != nil {
539 t.Fatal(err)
541 defer ln.Close()
542 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
543 if err != nil {
544 t.Fatal(err)
546 defer c.Close()
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++ {
561 err = c.Close()
562 if perr := parseCloseError(err); perr != nil {
563 t.Errorf("#%d: %v", i, perr)
565 err = ln.Close()
566 if perr := parseCloseError(err); perr != nil {
567 t.Errorf("#%d: %v", i, perr)
571 pc, err := ListenPacket("udp", "127.0.0.1:0")
572 if err != nil {
573 t.Fatal(err)
575 defer pc.Close()
577 for i := 0; i < 3; i++ {
578 err = pc.Close()
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 {
590 return nil
593 switch err := nestedErr.(type) {
594 case *OpError:
595 if err := err.isValid(); err != nil {
596 return err
598 nestedErr = err.Err
599 goto second
601 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
603 second:
604 if isPlatformError(nestedErr) {
605 return nil
607 switch err := nestedErr.(type) {
608 case *os.SyscallError:
609 nestedErr = err.Err
610 goto third
611 case *os.PathError: // for Plan 9
612 nestedErr = err.Err
613 goto third
615 switch nestedErr {
616 case errClosing, errTimeout:
617 return nil
619 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
621 third:
622 if isPlatformError(nestedErr) {
623 return nil
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) {
630 for {
631 ln.(*TCPListener).SetDeadline(time.Now().Add(5 * time.Millisecond))
632 c, err := ln.Accept()
633 if perr := parseAcceptError(err); perr != nil {
634 t.Error(perr)
636 if err != nil {
637 if c != 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()) {
641 return
643 continue
645 c.Close()
648 ls, err := newLocalServer("tcp")
649 if err != nil {
650 t.Fatal(err)
652 if err := ls.buildup(handler); err != nil {
653 ls.teardown()
654 t.Fatal(err)
657 time.Sleep(100 * time.Millisecond)
658 ls.teardown()
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 {
666 return nil
669 switch err := nestedErr.(type) {
670 case *OpError:
671 if err := err.isValid(); err != nil {
672 return err
674 nestedErr = err.Err
675 goto second
677 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
679 second:
680 if isPlatformError(nestedErr) {
681 return nil
683 switch err := nestedErr.(type) {
684 case *os.SyscallError:
685 nestedErr = err.Err
686 goto third
687 case *os.LinkError:
688 nestedErr = err.Err
689 goto third
690 case *os.PathError:
691 nestedErr = err.Err
692 goto third
694 switch nestedErr {
695 case errClosing:
696 return nil
698 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
700 third:
701 if isPlatformError(nestedErr) {
702 return nil
704 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
707 func TestFileError(t *testing.T) {
708 switch runtime.GOOS {
709 case "windows":
710 t.Skipf("not supported on %s", runtime.GOOS)
713 f, err := ioutil.TempFile("", "go-nettest")
714 if err != nil {
715 t.Fatal(err)
717 defer os.Remove(f.Name())
718 defer f.Close()
720 c, err := FileConn(f)
721 if err != nil {
722 if c != nil {
723 t.Errorf("FileConn returned non-nil interface %T(%v) with err != nil", c, c)
725 if perr := parseCommonError(err); perr != nil {
726 t.Error(perr)
728 } else {
729 c.Close()
730 t.Error("should fail")
732 ln, err := FileListener(f)
733 if err != nil {
734 if ln != nil {
735 t.Errorf("FileListener returned non-nil interface %T(%v) with err != nil", ln, ln)
737 if perr := parseCommonError(err); perr != nil {
738 t.Error(perr)
740 } else {
741 ln.Close()
742 t.Error("should fail")
744 pc, err := FilePacketConn(f)
745 if err != nil {
746 if pc != nil {
747 t.Errorf("FilePacketConn returned non-nil interface %T(%v) with err != nil", pc, pc)
749 if perr := parseCommonError(err); perr != nil {
750 t.Error(perr)
752 } else {
753 pc.Close()
754 t.Error("should fail")
757 ln, err = newLocalListener("tcp")
758 if err != nil {
759 t.Fatal(err)
762 for i := 0; i < 3; i++ {
763 f, err := ln.(*TCPListener).File()
764 if err != nil {
765 if perr := parseCommonError(err); perr != nil {
766 t.Error(perr)
768 } else {
769 f.Close()
771 ln.Close()
775 func parseLookupPortError(nestedErr error) error {
776 if nestedErr == nil {
777 return nil
780 switch nestedErr.(type) {
781 case *AddrError, *DNSError:
782 return nil
783 case *os.PathError: // for Plan 9
784 return nil
786 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)