runtime: add special handling for signal 34
[official-gcc.git] / libgo / go / net / error_test.go
blob4a191673e2fcb22101a2d7a58c4459166d17a2d0
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 //go:build !js
7 package net
9 import (
10 "context"
11 "errors"
12 "fmt"
13 "internal/poll"
14 "io"
15 "io/fs"
16 "net/internal/socktest"
17 "os"
18 "runtime"
19 "strings"
20 "testing"
21 "time"
24 func (e *OpError) isValid() error {
25 if e.Op == "" {
26 return fmt.Errorf("OpError.Op is empty: %v", e)
28 if e.Net == "" {
29 return fmt.Errorf("OpError.Net is empty: %v", e)
31 for _, addr := range []Addr{e.Source, e.Addr} {
32 switch addr := addr.(type) {
33 case nil:
34 case *TCPAddr:
35 if addr == nil {
36 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
38 case *UDPAddr:
39 if addr == nil {
40 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
42 case *IPAddr:
43 if addr == nil {
44 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
46 case *IPNet:
47 if addr == nil {
48 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
50 case *UnixAddr:
51 if addr == nil {
52 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
54 case *pipeAddr:
55 if addr == nil {
56 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
58 case fileAddr:
59 if addr == "" {
60 return fmt.Errorf("OpError.Source or Addr is empty: %#v, %v", addr, e)
62 default:
63 return fmt.Errorf("OpError.Source or Addr is unknown type: %T, %v", addr, e)
66 if e.Err == nil {
67 return fmt.Errorf("OpError.Err is empty: %v", e)
69 return nil
72 // parseDialError parses nestedErr and reports whether it is a valid
73 // error value from Dial, Listen functions.
74 // It returns nil when nestedErr is valid.
75 func parseDialError(nestedErr error) error {
76 if nestedErr == nil {
77 return nil
80 switch err := nestedErr.(type) {
81 case *OpError:
82 if err := err.isValid(); err != nil {
83 return err
85 nestedErr = err.Err
86 goto second
88 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
90 second:
91 if isPlatformError(nestedErr) {
92 return nil
94 switch err := nestedErr.(type) {
95 case *AddrError, addrinfoErrno, *timeoutError, *DNSError, InvalidAddrError, *ParseError, *poll.DeadlineExceededError, UnknownNetworkError:
96 return nil
97 case *os.SyscallError:
98 nestedErr = err.Err
99 goto third
100 case *fs.PathError: // for Plan 9
101 nestedErr = err.Err
102 goto third
104 switch nestedErr {
105 case errCanceled, ErrClosed, errMissingAddress, errNoSuitableAddress,
106 context.DeadlineExceeded, context.Canceled:
107 return nil
109 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
111 third:
112 if isPlatformError(nestedErr) {
113 return nil
115 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
118 var dialErrorTests = []struct {
119 network, address string
121 {"foo", ""},
122 {"bar", "baz"},
123 {"datakit", "mh/astro/r70"},
124 {"tcp", ""},
125 {"tcp", "127.0.0.1:☺"},
126 {"tcp", "no-such-name:80"},
127 {"tcp", "mh/astro/r70:http"},
129 {"tcp", JoinHostPort("127.0.0.1", "-1")},
130 {"tcp", JoinHostPort("127.0.0.1", "123456789")},
131 {"udp", JoinHostPort("127.0.0.1", "-1")},
132 {"udp", JoinHostPort("127.0.0.1", "123456789")},
133 {"ip:icmp", "127.0.0.1"},
135 {"unix", "/path/to/somewhere"},
136 {"unixgram", "/path/to/somewhere"},
137 {"unixpacket", "/path/to/somewhere"},
140 func TestDialError(t *testing.T) {
141 switch runtime.GOOS {
142 case "plan9":
143 t.Skipf("%s does not have full support of socktest", runtime.GOOS)
146 origTestHookLookupIP := testHookLookupIP
147 defer func() { testHookLookupIP = origTestHookLookupIP }()
148 testHookLookupIP = func(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
149 return nil, &DNSError{Err: "dial error test", Name: "name", Server: "server", IsTimeout: true}
151 sw.Set(socktest.FilterConnect, func(so *socktest.Status) (socktest.AfterFilter, error) {
152 return nil, errOpNotSupported
154 defer sw.Set(socktest.FilterConnect, nil)
156 d := Dialer{Timeout: someTimeout}
157 for i, tt := range dialErrorTests {
158 c, err := d.Dial(tt.network, tt.address)
159 if err == nil {
160 t.Errorf("#%d: should fail; %s:%s->%s", i, c.LocalAddr().Network(), c.LocalAddr(), c.RemoteAddr())
161 c.Close()
162 continue
164 if tt.network == "tcp" || tt.network == "udp" {
165 nerr := err
166 if op, ok := nerr.(*OpError); ok {
167 nerr = op.Err
169 if sys, ok := nerr.(*os.SyscallError); ok {
170 nerr = sys.Err
172 if nerr == errOpNotSupported {
173 t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
174 continue
177 if c != nil {
178 t.Errorf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
180 if err = parseDialError(err); err != nil {
181 t.Errorf("#%d: %v", i, err)
182 continue
187 func TestProtocolDialError(t *testing.T) {
188 switch runtime.GOOS {
189 case "solaris", "illumos":
190 t.Skipf("not supported on %s", runtime.GOOS)
193 for _, network := range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
194 var err error
195 switch network {
196 case "tcp":
197 _, err = DialTCP(network, nil, &TCPAddr{Port: 1 << 16})
198 case "udp":
199 _, err = DialUDP(network, nil, &UDPAddr{Port: 1 << 16})
200 case "ip:4294967296":
201 _, err = DialIP(network, nil, nil)
202 case "unix", "unixpacket", "unixgram":
203 _, err = DialUnix(network, nil, &UnixAddr{Name: "//"})
205 if err == nil {
206 t.Errorf("%s: should fail", network)
207 continue
209 if err = parseDialError(err); err != nil {
210 t.Errorf("%s: %v", network, err)
211 continue
216 func TestDialAddrError(t *testing.T) {
217 switch runtime.GOOS {
218 case "plan9":
219 t.Skipf("not supported on %s", runtime.GOOS)
221 if !supportsIPv4() || !supportsIPv6() {
222 t.Skip("both IPv4 and IPv6 are required")
225 for _, tt := range []struct {
226 network string
227 lit string
228 addr *TCPAddr
230 {"tcp4", "::1", nil},
231 {"tcp4", "", &TCPAddr{IP: IPv6loopback}},
232 // We don't test the {"tcp6", "byte sequence", nil}
233 // case for now because there is no easy way to
234 // control name resolution.
235 {"tcp6", "", &TCPAddr{IP: IP{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}}},
237 var err error
238 var c Conn
239 var op string
240 if tt.lit != "" {
241 c, err = Dial(tt.network, JoinHostPort(tt.lit, "0"))
242 op = fmt.Sprintf("Dial(%q, %q)", tt.network, JoinHostPort(tt.lit, "0"))
243 } else {
244 c, err = DialTCP(tt.network, nil, tt.addr)
245 op = fmt.Sprintf("DialTCP(%q, %q)", tt.network, tt.addr)
247 if err == nil {
248 c.Close()
249 t.Errorf("%s succeeded, want error", op)
250 continue
252 if perr := parseDialError(err); perr != nil {
253 t.Errorf("%s: %v", op, perr)
254 continue
256 operr := err.(*OpError).Err
257 aerr, ok := operr.(*AddrError)
258 if !ok {
259 t.Errorf("%s: %v is %T, want *AddrError", op, err, operr)
260 continue
262 want := tt.lit
263 if tt.lit == "" {
264 want = tt.addr.IP.String()
266 if aerr.Addr != want {
267 t.Errorf("%s: %v, error Addr=%q, want %q", op, err, aerr.Addr, want)
272 var listenErrorTests = []struct {
273 network, address string
275 {"foo", ""},
276 {"bar", "baz"},
277 {"datakit", "mh/astro/r70"},
278 {"tcp", "127.0.0.1:☺"},
279 {"tcp", "no-such-name:80"},
280 {"tcp", "mh/astro/r70:http"},
282 {"tcp", JoinHostPort("127.0.0.1", "-1")},
283 {"tcp", JoinHostPort("127.0.0.1", "123456789")},
285 {"unix", "/path/to/somewhere"},
286 {"unixpacket", "/path/to/somewhere"},
289 func TestListenError(t *testing.T) {
290 switch runtime.GOOS {
291 case "plan9":
292 t.Skipf("%s does not have full support of socktest", runtime.GOOS)
295 origTestHookLookupIP := testHookLookupIP
296 defer func() { testHookLookupIP = origTestHookLookupIP }()
297 testHookLookupIP = func(_ context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
298 return nil, &DNSError{Err: "listen error test", Name: "name", Server: "server", IsTimeout: true}
300 sw.Set(socktest.FilterListen, func(so *socktest.Status) (socktest.AfterFilter, error) {
301 return nil, errOpNotSupported
303 defer sw.Set(socktest.FilterListen, nil)
305 for i, tt := range listenErrorTests {
306 ln, err := Listen(tt.network, tt.address)
307 if err == nil {
308 t.Errorf("#%d: should fail; %s:%s->", i, ln.Addr().Network(), ln.Addr())
309 ln.Close()
310 continue
312 if tt.network == "tcp" {
313 nerr := err
314 if op, ok := nerr.(*OpError); ok {
315 nerr = op.Err
317 if sys, ok := nerr.(*os.SyscallError); ok {
318 nerr = sys.Err
320 if nerr == errOpNotSupported {
321 t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
322 continue
325 if ln != nil {
326 t.Errorf("Listen returned non-nil interface %T(%v) with err != nil", ln, ln)
328 if err = parseDialError(err); err != nil {
329 t.Errorf("#%d: %v", i, err)
330 continue
335 var listenPacketErrorTests = []struct {
336 network, address string
338 {"foo", ""},
339 {"bar", "baz"},
340 {"datakit", "mh/astro/r70"},
341 {"udp", "127.0.0.1:☺"},
342 {"udp", "no-such-name:80"},
343 {"udp", "mh/astro/r70:http"},
345 {"udp", JoinHostPort("127.0.0.1", "-1")},
346 {"udp", JoinHostPort("127.0.0.1", "123456789")},
349 func TestListenPacketError(t *testing.T) {
350 switch runtime.GOOS {
351 case "plan9":
352 t.Skipf("%s does not have full support of socktest", runtime.GOOS)
355 origTestHookLookupIP := testHookLookupIP
356 defer func() { testHookLookupIP = origTestHookLookupIP }()
357 testHookLookupIP = func(_ context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
358 return nil, &DNSError{Err: "listen error test", Name: "name", Server: "server", IsTimeout: true}
361 for i, tt := range listenPacketErrorTests {
362 c, err := ListenPacket(tt.network, tt.address)
363 if err == nil {
364 t.Errorf("#%d: should fail; %s:%s->", i, c.LocalAddr().Network(), c.LocalAddr())
365 c.Close()
366 continue
368 if c != nil {
369 t.Errorf("ListenPacket returned non-nil interface %T(%v) with err != nil", c, c)
371 if err = parseDialError(err); err != nil {
372 t.Errorf("#%d: %v", i, err)
373 continue
378 func TestProtocolListenError(t *testing.T) {
379 switch runtime.GOOS {
380 case "plan9":
381 t.Skipf("not supported on %s", runtime.GOOS)
384 for _, network := range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
385 var err error
386 switch network {
387 case "tcp":
388 _, err = ListenTCP(network, &TCPAddr{Port: 1 << 16})
389 case "udp":
390 _, err = ListenUDP(network, &UDPAddr{Port: 1 << 16})
391 case "ip:4294967296":
392 _, err = ListenIP(network, nil)
393 case "unix", "unixpacket":
394 _, err = ListenUnix(network, &UnixAddr{Name: "//"})
395 case "unixgram":
396 _, err = ListenUnixgram(network, &UnixAddr{Name: "//"})
398 if err == nil {
399 t.Errorf("%s: should fail", network)
400 continue
402 if err = parseDialError(err); err != nil {
403 t.Errorf("%s: %v", network, err)
404 continue
409 // parseReadError parses nestedErr and reports whether it is a valid
410 // error value from Read functions.
411 // It returns nil when nestedErr is valid.
412 func parseReadError(nestedErr error) error {
413 if nestedErr == nil {
414 return nil
417 switch err := nestedErr.(type) {
418 case *OpError:
419 if err := err.isValid(); err != nil {
420 return err
422 nestedErr = err.Err
423 goto second
425 if nestedErr == io.EOF {
426 return nil
428 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
430 second:
431 if isPlatformError(nestedErr) {
432 return nil
434 switch err := nestedErr.(type) {
435 case *os.SyscallError:
436 nestedErr = err.Err
437 goto third
439 switch nestedErr {
440 case ErrClosed, errTimeout, poll.ErrNotPollable, os.ErrDeadlineExceeded:
441 return nil
443 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
445 third:
446 if isPlatformError(nestedErr) {
447 return nil
449 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
452 // parseWriteError parses nestedErr and reports whether it is a valid
453 // error value from Write functions.
454 // It returns nil when nestedErr is valid.
455 func parseWriteError(nestedErr error) error {
456 if nestedErr == nil {
457 return nil
460 switch err := nestedErr.(type) {
461 case *OpError:
462 if err := err.isValid(); err != nil {
463 return err
465 nestedErr = err.Err
466 goto second
468 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
470 second:
471 if isPlatformError(nestedErr) {
472 return nil
474 switch err := nestedErr.(type) {
475 case *AddrError, addrinfoErrno, *timeoutError, *DNSError, InvalidAddrError, *ParseError, *poll.DeadlineExceededError, UnknownNetworkError:
476 return nil
477 case *os.SyscallError:
478 nestedErr = err.Err
479 goto third
481 switch nestedErr {
482 case errCanceled, ErrClosed, errMissingAddress, errTimeout, os.ErrDeadlineExceeded, ErrWriteToConnected, io.ErrUnexpectedEOF:
483 return nil
485 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
487 third:
488 if isPlatformError(nestedErr) {
489 return nil
491 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
494 // parseCloseError parses nestedErr and reports whether it is a valid
495 // error value from Close functions.
496 // It returns nil when nestedErr is valid.
497 func parseCloseError(nestedErr error, isShutdown bool) error {
498 if nestedErr == nil {
499 return nil
502 // Because historically we have not exported the error that we
503 // return for an operation on a closed network connection,
504 // there are programs that test for the exact error string.
505 // Verify that string here so that we don't break those
506 // programs unexpectedly. See issues #4373 and #19252.
507 want := "use of closed network connection"
508 if !isShutdown && !strings.Contains(nestedErr.Error(), want) {
509 return fmt.Errorf("error string %q does not contain expected string %q", nestedErr, want)
512 if !isShutdown && !errors.Is(nestedErr, ErrClosed) {
513 return fmt.Errorf("errors.Is(%v, errClosed) returns false, want true", nestedErr)
516 switch err := nestedErr.(type) {
517 case *OpError:
518 if err := err.isValid(); err != nil {
519 return err
521 nestedErr = err.Err
522 goto second
524 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
526 second:
527 if isPlatformError(nestedErr) {
528 return nil
530 switch err := nestedErr.(type) {
531 case *os.SyscallError:
532 nestedErr = err.Err
533 goto third
534 case *fs.PathError: // for Plan 9
535 nestedErr = err.Err
536 goto third
538 switch nestedErr {
539 case ErrClosed:
540 return nil
542 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
544 third:
545 if isPlatformError(nestedErr) {
546 return nil
548 switch nestedErr {
549 case fs.ErrClosed: // for Plan 9
550 return nil
552 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
555 func TestCloseError(t *testing.T) {
556 ln := newLocalListener(t, "tcp")
557 defer ln.Close()
558 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
559 if err != nil {
560 t.Fatal(err)
562 defer c.Close()
564 for i := 0; i < 3; i++ {
565 err = c.(*TCPConn).CloseRead()
566 if perr := parseCloseError(err, true); perr != nil {
567 t.Errorf("#%d: %v", i, perr)
570 for i := 0; i < 3; i++ {
571 err = c.(*TCPConn).CloseWrite()
572 if perr := parseCloseError(err, true); perr != nil {
573 t.Errorf("#%d: %v", i, perr)
576 for i := 0; i < 3; i++ {
577 err = c.Close()
578 if perr := parseCloseError(err, false); perr != nil {
579 t.Errorf("#%d: %v", i, perr)
581 err = ln.Close()
582 if perr := parseCloseError(err, false); perr != nil {
583 t.Errorf("#%d: %v", i, perr)
587 pc, err := ListenPacket("udp", "127.0.0.1:0")
588 if err != nil {
589 t.Fatal(err)
591 defer pc.Close()
593 for i := 0; i < 3; i++ {
594 err = pc.Close()
595 if perr := parseCloseError(err, false); perr != nil {
596 t.Errorf("#%d: %v", i, perr)
601 // parseAcceptError parses nestedErr and reports whether it is a valid
602 // error value from Accept functions.
603 // It returns nil when nestedErr is valid.
604 func parseAcceptError(nestedErr error) error {
605 if nestedErr == nil {
606 return nil
609 switch err := nestedErr.(type) {
610 case *OpError:
611 if err := err.isValid(); err != nil {
612 return err
614 nestedErr = err.Err
615 goto second
617 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
619 second:
620 if isPlatformError(nestedErr) {
621 return nil
623 switch err := nestedErr.(type) {
624 case *os.SyscallError:
625 nestedErr = err.Err
626 goto third
627 case *fs.PathError: // for Plan 9
628 nestedErr = err.Err
629 goto third
631 switch nestedErr {
632 case ErrClosed, errTimeout, poll.ErrNotPollable, os.ErrDeadlineExceeded:
633 return nil
635 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
637 third:
638 if isPlatformError(nestedErr) {
639 return nil
641 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
644 func TestAcceptError(t *testing.T) {
645 handler := func(ls *localServer, ln Listener) {
646 for {
647 ln.(*TCPListener).SetDeadline(time.Now().Add(5 * time.Millisecond))
648 c, err := ln.Accept()
649 if perr := parseAcceptError(err); perr != nil {
650 t.Error(perr)
652 if err != nil {
653 if c != nil {
654 t.Errorf("Accept returned non-nil interface %T(%v) with err != nil", c, c)
656 if nerr, ok := err.(Error); !ok || (!nerr.Timeout() && !nerr.Temporary()) {
657 return
659 continue
661 c.Close()
664 ls := newLocalServer(t, "tcp")
665 if err := ls.buildup(handler); err != nil {
666 ls.teardown()
667 t.Fatal(err)
670 time.Sleep(100 * time.Millisecond)
671 ls.teardown()
674 // parseCommonError parses nestedErr and reports whether it is a valid
675 // error value from miscellaneous functions.
676 // It returns nil when nestedErr is valid.
677 func parseCommonError(nestedErr error) error {
678 if nestedErr == nil {
679 return nil
682 switch err := nestedErr.(type) {
683 case *OpError:
684 if err := err.isValid(); err != nil {
685 return err
687 nestedErr = err.Err
688 goto second
690 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
692 second:
693 if isPlatformError(nestedErr) {
694 return nil
696 switch err := nestedErr.(type) {
697 case *os.SyscallError:
698 nestedErr = err.Err
699 goto third
700 case *os.LinkError:
701 nestedErr = err.Err
702 goto third
703 case *fs.PathError:
704 nestedErr = err.Err
705 goto third
707 switch nestedErr {
708 case ErrClosed:
709 return nil
711 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
713 third:
714 if isPlatformError(nestedErr) {
715 return nil
717 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
720 func TestFileError(t *testing.T) {
721 switch runtime.GOOS {
722 case "windows":
723 t.Skipf("not supported on %s", runtime.GOOS)
726 f, err := os.CreateTemp("", "go-nettest")
727 if err != nil {
728 t.Fatal(err)
730 defer os.Remove(f.Name())
731 defer f.Close()
733 c, err := FileConn(f)
734 if err != nil {
735 if c != nil {
736 t.Errorf("FileConn returned non-nil interface %T(%v) with err != nil", c, c)
738 if perr := parseCommonError(err); perr != nil {
739 t.Error(perr)
741 } else {
742 c.Close()
743 t.Error("should fail")
745 ln, err := FileListener(f)
746 if err != nil {
747 if ln != nil {
748 t.Errorf("FileListener returned non-nil interface %T(%v) with err != nil", ln, ln)
750 if perr := parseCommonError(err); perr != nil {
751 t.Error(perr)
753 } else {
754 ln.Close()
755 t.Error("should fail")
757 pc, err := FilePacketConn(f)
758 if err != nil {
759 if pc != nil {
760 t.Errorf("FilePacketConn returned non-nil interface %T(%v) with err != nil", pc, pc)
762 if perr := parseCommonError(err); perr != nil {
763 t.Error(perr)
765 } else {
766 pc.Close()
767 t.Error("should fail")
770 ln = newLocalListener(t, "tcp")
772 for i := 0; i < 3; i++ {
773 f, err := ln.(*TCPListener).File()
774 if err != nil {
775 if perr := parseCommonError(err); perr != nil {
776 t.Error(perr)
778 } else {
779 f.Close()
781 ln.Close()
785 func parseLookupPortError(nestedErr error) error {
786 if nestedErr == nil {
787 return nil
790 switch nestedErr.(type) {
791 case *AddrError, *DNSError:
792 return nil
793 case *fs.PathError: // for Plan 9
794 return nil
796 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)