Source file
src/net/error_test.go
1
2
3
4
5
6
7 package net
8
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"
22 )
23
24 func (e *OpError) isValid() error {
25 if e.Op == "" {
26 return fmt.Errorf("OpError.Op is empty: %v", e)
27 }
28 if e.Net == "" {
29 return fmt.Errorf("OpError.Net is empty: %v", e)
30 }
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)
37 }
38 case *UDPAddr:
39 if addr == nil {
40 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
41 }
42 case *IPAddr:
43 if addr == nil {
44 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
45 }
46 case *IPNet:
47 if addr == nil {
48 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
49 }
50 case *UnixAddr:
51 if addr == nil {
52 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
53 }
54 case *pipeAddr:
55 if addr == nil {
56 return fmt.Errorf("OpError.Source or Addr is non-nil interface: %#v, %v", addr, e)
57 }
58 case fileAddr:
59 if addr == "" {
60 return fmt.Errorf("OpError.Source or Addr is empty: %#v, %v", addr, e)
61 }
62 default:
63 return fmt.Errorf("OpError.Source or Addr is unknown type: %T, %v", addr, e)
64 }
65 }
66 if e.Err == nil {
67 return fmt.Errorf("OpError.Err is empty: %v", e)
68 }
69 return nil
70 }
71
72
73
74
75 func parseDialError(nestedErr error) error {
76 if nestedErr == nil {
77 return nil
78 }
79
80 switch err := nestedErr.(type) {
81 case *OpError:
82 if err := err.isValid(); err != nil {
83 return err
84 }
85 nestedErr = err.Err
86 goto second
87 }
88 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
89
90 second:
91 if isPlatformError(nestedErr) {
92 return nil
93 }
94 switch err := nestedErr.(type) {
95 case *AddrError, *timeoutError, *DNSError, InvalidAddrError, *ParseError, *poll.DeadlineExceededError, UnknownNetworkError:
96 return nil
97 case interface{ isAddrinfoErrno() }:
98 return nil
99 case *os.SyscallError:
100 nestedErr = err.Err
101 goto third
102 case *fs.PathError:
103 nestedErr = err.Err
104 goto third
105 }
106 switch nestedErr {
107 case errCanceled, ErrClosed, errMissingAddress, errNoSuitableAddress,
108 context.DeadlineExceeded, context.Canceled:
109 return nil
110 }
111 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
112
113 third:
114 if isPlatformError(nestedErr) {
115 return nil
116 }
117 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
118 }
119
120 var dialErrorTests = []struct {
121 network, address string
122 }{
123 {"foo", ""},
124 {"bar", "baz"},
125 {"datakit", "mh/astro/r70"},
126 {"tcp", ""},
127 {"tcp", "127.0.0.1:☺"},
128 {"tcp", "no-such-name:80"},
129 {"tcp", "mh/astro/r70:http"},
130
131 {"tcp", JoinHostPort("127.0.0.1", "-1")},
132 {"tcp", JoinHostPort("127.0.0.1", "123456789")},
133 {"udp", JoinHostPort("127.0.0.1", "-1")},
134 {"udp", JoinHostPort("127.0.0.1", "123456789")},
135 {"ip:icmp", "127.0.0.1"},
136
137 {"unix", "/path/to/somewhere"},
138 {"unixgram", "/path/to/somewhere"},
139 {"unixpacket", "/path/to/somewhere"},
140 }
141
142 func TestDialError(t *testing.T) {
143 switch runtime.GOOS {
144 case "plan9":
145 t.Skipf("%s does not have full support of socktest", runtime.GOOS)
146 }
147
148 origTestHookLookupIP := testHookLookupIP
149 defer func() { testHookLookupIP = origTestHookLookupIP }()
150 testHookLookupIP = func(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
151 return nil, &DNSError{Err: "dial error test", Name: "name", Server: "server", IsTimeout: true}
152 }
153 sw.Set(socktest.FilterConnect, func(so *socktest.Status) (socktest.AfterFilter, error) {
154 return nil, errOpNotSupported
155 })
156 defer sw.Set(socktest.FilterConnect, nil)
157
158 d := Dialer{Timeout: someTimeout}
159 for i, tt := range dialErrorTests {
160 c, err := d.Dial(tt.network, tt.address)
161 if err == nil {
162 t.Errorf("#%d: should fail; %s:%s->%s", i, c.LocalAddr().Network(), c.LocalAddr(), c.RemoteAddr())
163 c.Close()
164 continue
165 }
166 if tt.network == "tcp" || tt.network == "udp" {
167 nerr := err
168 if op, ok := nerr.(*OpError); ok {
169 nerr = op.Err
170 }
171 if sys, ok := nerr.(*os.SyscallError); ok {
172 nerr = sys.Err
173 }
174 if nerr == errOpNotSupported {
175 t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
176 continue
177 }
178 }
179 if c != nil {
180 t.Errorf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
181 }
182 if err = parseDialError(err); err != nil {
183 t.Errorf("#%d: %v", i, err)
184 continue
185 }
186 }
187 }
188
189 func TestProtocolDialError(t *testing.T) {
190 switch runtime.GOOS {
191 case "solaris", "illumos":
192 t.Skipf("not supported on %s", runtime.GOOS)
193 }
194
195 for _, network := range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
196 var err error
197 switch network {
198 case "tcp":
199 _, err = DialTCP(network, nil, &TCPAddr{Port: 1 << 16})
200 case "udp":
201 _, err = DialUDP(network, nil, &UDPAddr{Port: 1 << 16})
202 case "ip:4294967296":
203 _, err = DialIP(network, nil, nil)
204 case "unix", "unixpacket", "unixgram":
205 _, err = DialUnix(network, nil, &UnixAddr{Name: "//"})
206 }
207 if err == nil {
208 t.Errorf("%s: should fail", network)
209 continue
210 }
211 if err = parseDialError(err); err != nil {
212 t.Errorf("%s: %v", network, err)
213 continue
214 }
215 }
216 }
217
218 func TestDialAddrError(t *testing.T) {
219 switch runtime.GOOS {
220 case "plan9":
221 t.Skipf("not supported on %s", runtime.GOOS)
222 }
223 if !supportsIPv4() || !supportsIPv6() {
224 t.Skip("both IPv4 and IPv6 are required")
225 }
226
227 for _, tt := range []struct {
228 network string
229 lit string
230 addr *TCPAddr
231 }{
232 {"tcp4", "::1", nil},
233 {"tcp4", "", &TCPAddr{IP: IPv6loopback}},
234
235
236
237 {"tcp6", "", &TCPAddr{IP: IP{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}}},
238 } {
239 var err error
240 var c Conn
241 var op string
242 if tt.lit != "" {
243 c, err = Dial(tt.network, JoinHostPort(tt.lit, "0"))
244 op = fmt.Sprintf("Dial(%q, %q)", tt.network, JoinHostPort(tt.lit, "0"))
245 } else {
246 c, err = DialTCP(tt.network, nil, tt.addr)
247 op = fmt.Sprintf("DialTCP(%q, %q)", tt.network, tt.addr)
248 }
249 if err == nil {
250 c.Close()
251 t.Errorf("%s succeeded, want error", op)
252 continue
253 }
254 if perr := parseDialError(err); perr != nil {
255 t.Errorf("%s: %v", op, perr)
256 continue
257 }
258 operr := err.(*OpError).Err
259 aerr, ok := operr.(*AddrError)
260 if !ok {
261 t.Errorf("%s: %v is %T, want *AddrError", op, err, operr)
262 continue
263 }
264 want := tt.lit
265 if tt.lit == "" {
266 want = tt.addr.IP.String()
267 }
268 if aerr.Addr != want {
269 t.Errorf("%s: %v, error Addr=%q, want %q", op, err, aerr.Addr, want)
270 }
271 }
272 }
273
274 var listenErrorTests = []struct {
275 network, address string
276 }{
277 {"foo", ""},
278 {"bar", "baz"},
279 {"datakit", "mh/astro/r70"},
280 {"tcp", "127.0.0.1:☺"},
281 {"tcp", "no-such-name:80"},
282 {"tcp", "mh/astro/r70:http"},
283
284 {"tcp", JoinHostPort("127.0.0.1", "-1")},
285 {"tcp", JoinHostPort("127.0.0.1", "123456789")},
286
287 {"unix", "/path/to/somewhere"},
288 {"unixpacket", "/path/to/somewhere"},
289 }
290
291 func TestListenError(t *testing.T) {
292 switch runtime.GOOS {
293 case "plan9":
294 t.Skipf("%s does not have full support of socktest", runtime.GOOS)
295 }
296
297 origTestHookLookupIP := testHookLookupIP
298 defer func() { testHookLookupIP = origTestHookLookupIP }()
299 testHookLookupIP = func(_ context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
300 return nil, &DNSError{Err: "listen error test", Name: "name", Server: "server", IsTimeout: true}
301 }
302 sw.Set(socktest.FilterListen, func(so *socktest.Status) (socktest.AfterFilter, error) {
303 return nil, errOpNotSupported
304 })
305 defer sw.Set(socktest.FilterListen, nil)
306
307 for i, tt := range listenErrorTests {
308 ln, err := Listen(tt.network, tt.address)
309 if err == nil {
310 t.Errorf("#%d: should fail; %s:%s->", i, ln.Addr().Network(), ln.Addr())
311 ln.Close()
312 continue
313 }
314 if tt.network == "tcp" {
315 nerr := err
316 if op, ok := nerr.(*OpError); ok {
317 nerr = op.Err
318 }
319 if sys, ok := nerr.(*os.SyscallError); ok {
320 nerr = sys.Err
321 }
322 if nerr == errOpNotSupported {
323 t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
324 continue
325 }
326 }
327 if ln != nil {
328 t.Errorf("Listen returned non-nil interface %T(%v) with err != nil", ln, ln)
329 }
330 if err = parseDialError(err); err != nil {
331 t.Errorf("#%d: %v", i, err)
332 continue
333 }
334 }
335 }
336
337 var listenPacketErrorTests = []struct {
338 network, address string
339 }{
340 {"foo", ""},
341 {"bar", "baz"},
342 {"datakit", "mh/astro/r70"},
343 {"udp", "127.0.0.1:☺"},
344 {"udp", "no-such-name:80"},
345 {"udp", "mh/astro/r70:http"},
346
347 {"udp", JoinHostPort("127.0.0.1", "-1")},
348 {"udp", JoinHostPort("127.0.0.1", "123456789")},
349 }
350
351 func TestListenPacketError(t *testing.T) {
352 switch runtime.GOOS {
353 case "plan9":
354 t.Skipf("%s does not have full support of socktest", runtime.GOOS)
355 }
356
357 origTestHookLookupIP := testHookLookupIP
358 defer func() { testHookLookupIP = origTestHookLookupIP }()
359 testHookLookupIP = func(_ context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
360 return nil, &DNSError{Err: "listen error test", Name: "name", Server: "server", IsTimeout: true}
361 }
362
363 for i, tt := range listenPacketErrorTests {
364 c, err := ListenPacket(tt.network, tt.address)
365 if err == nil {
366 t.Errorf("#%d: should fail; %s:%s->", i, c.LocalAddr().Network(), c.LocalAddr())
367 c.Close()
368 continue
369 }
370 if c != nil {
371 t.Errorf("ListenPacket returned non-nil interface %T(%v) with err != nil", c, c)
372 }
373 if err = parseDialError(err); err != nil {
374 t.Errorf("#%d: %v", i, err)
375 continue
376 }
377 }
378 }
379
380 func TestProtocolListenError(t *testing.T) {
381 switch runtime.GOOS {
382 case "plan9":
383 t.Skipf("not supported on %s", runtime.GOOS)
384 }
385
386 for _, network := range []string{"tcp", "udp", "ip:4294967296", "unix", "unixpacket", "unixgram"} {
387 var err error
388 switch network {
389 case "tcp":
390 _, err = ListenTCP(network, &TCPAddr{Port: 1 << 16})
391 case "udp":
392 _, err = ListenUDP(network, &UDPAddr{Port: 1 << 16})
393 case "ip:4294967296":
394 _, err = ListenIP(network, nil)
395 case "unix", "unixpacket":
396 _, err = ListenUnix(network, &UnixAddr{Name: "//"})
397 case "unixgram":
398 _, err = ListenUnixgram(network, &UnixAddr{Name: "//"})
399 }
400 if err == nil {
401 t.Errorf("%s: should fail", network)
402 continue
403 }
404 if err = parseDialError(err); err != nil {
405 t.Errorf("%s: %v", network, err)
406 continue
407 }
408 }
409 }
410
411
412
413
414 func parseReadError(nestedErr error) error {
415 if nestedErr == nil {
416 return nil
417 }
418
419 switch err := nestedErr.(type) {
420 case *OpError:
421 if err := err.isValid(); err != nil {
422 return err
423 }
424 nestedErr = err.Err
425 goto second
426 }
427 if nestedErr == io.EOF {
428 return nil
429 }
430 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
431
432 second:
433 if isPlatformError(nestedErr) {
434 return nil
435 }
436 switch err := nestedErr.(type) {
437 case *os.SyscallError:
438 nestedErr = err.Err
439 goto third
440 }
441 switch nestedErr {
442 case ErrClosed, errTimeout, poll.ErrNotPollable, os.ErrDeadlineExceeded:
443 return nil
444 }
445 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
446
447 third:
448 if isPlatformError(nestedErr) {
449 return nil
450 }
451 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
452 }
453
454
455
456
457 func parseWriteError(nestedErr error) error {
458 if nestedErr == nil {
459 return nil
460 }
461
462 switch err := nestedErr.(type) {
463 case *OpError:
464 if err := err.isValid(); err != nil {
465 return err
466 }
467 nestedErr = err.Err
468 goto second
469 }
470 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
471
472 second:
473 if isPlatformError(nestedErr) {
474 return nil
475 }
476 switch err := nestedErr.(type) {
477 case *AddrError, *timeoutError, *DNSError, InvalidAddrError, *ParseError, *poll.DeadlineExceededError, UnknownNetworkError:
478 return nil
479 case interface{ isAddrinfoErrno() }:
480 return nil
481 case *os.SyscallError:
482 nestedErr = err.Err
483 goto third
484 }
485 switch nestedErr {
486 case errCanceled, ErrClosed, errMissingAddress, errTimeout, os.ErrDeadlineExceeded, ErrWriteToConnected, io.ErrUnexpectedEOF:
487 return nil
488 }
489 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
490
491 third:
492 if isPlatformError(nestedErr) {
493 return nil
494 }
495 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
496 }
497
498
499
500
501 func parseCloseError(nestedErr error, isShutdown bool) error {
502 if nestedErr == nil {
503 return nil
504 }
505
506
507
508
509
510
511 want := "use of closed network connection"
512 if !isShutdown && !strings.Contains(nestedErr.Error(), want) {
513 return fmt.Errorf("error string %q does not contain expected string %q", nestedErr, want)
514 }
515
516 if !isShutdown && !errors.Is(nestedErr, ErrClosed) {
517 return fmt.Errorf("errors.Is(%v, errClosed) returns false, want true", nestedErr)
518 }
519
520 switch err := nestedErr.(type) {
521 case *OpError:
522 if err := err.isValid(); err != nil {
523 return err
524 }
525 nestedErr = err.Err
526 goto second
527 }
528 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
529
530 second:
531 if isPlatformError(nestedErr) {
532 return nil
533 }
534 switch err := nestedErr.(type) {
535 case *os.SyscallError:
536 nestedErr = err.Err
537 goto third
538 case *fs.PathError:
539 nestedErr = err.Err
540 goto third
541 }
542 switch nestedErr {
543 case ErrClosed:
544 return nil
545 }
546 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
547
548 third:
549 if isPlatformError(nestedErr) {
550 return nil
551 }
552 switch nestedErr {
553 case fs.ErrClosed:
554 return nil
555 }
556 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
557 }
558
559 func TestCloseError(t *testing.T) {
560 ln := newLocalListener(t, "tcp")
561 defer ln.Close()
562 c, err := Dial(ln.Addr().Network(), ln.Addr().String())
563 if err != nil {
564 t.Fatal(err)
565 }
566 defer c.Close()
567
568 for i := 0; i < 3; i++ {
569 err = c.(*TCPConn).CloseRead()
570 if perr := parseCloseError(err, true); perr != nil {
571 t.Errorf("#%d: %v", i, perr)
572 }
573 }
574 for i := 0; i < 3; i++ {
575 err = c.(*TCPConn).CloseWrite()
576 if perr := parseCloseError(err, true); perr != nil {
577 t.Errorf("#%d: %v", i, perr)
578 }
579 }
580 for i := 0; i < 3; i++ {
581 err = c.Close()
582 if perr := parseCloseError(err, false); perr != nil {
583 t.Errorf("#%d: %v", i, perr)
584 }
585 err = ln.Close()
586 if perr := parseCloseError(err, false); perr != nil {
587 t.Errorf("#%d: %v", i, perr)
588 }
589 }
590
591 pc, err := ListenPacket("udp", "127.0.0.1:0")
592 if err != nil {
593 t.Fatal(err)
594 }
595 defer pc.Close()
596
597 for i := 0; i < 3; i++ {
598 err = pc.Close()
599 if perr := parseCloseError(err, false); perr != nil {
600 t.Errorf("#%d: %v", i, perr)
601 }
602 }
603 }
604
605
606
607
608 func parseAcceptError(nestedErr error) error {
609 if nestedErr == nil {
610 return nil
611 }
612
613 switch err := nestedErr.(type) {
614 case *OpError:
615 if err := err.isValid(); err != nil {
616 return err
617 }
618 nestedErr = err.Err
619 goto second
620 }
621 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
622
623 second:
624 if isPlatformError(nestedErr) {
625 return nil
626 }
627 switch err := nestedErr.(type) {
628 case *os.SyscallError:
629 nestedErr = err.Err
630 goto third
631 case *fs.PathError:
632 nestedErr = err.Err
633 goto third
634 }
635 switch nestedErr {
636 case ErrClosed, errTimeout, poll.ErrNotPollable, os.ErrDeadlineExceeded:
637 return nil
638 }
639 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
640
641 third:
642 if isPlatformError(nestedErr) {
643 return nil
644 }
645 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
646 }
647
648 func TestAcceptError(t *testing.T) {
649 handler := func(ls *localServer, ln Listener) {
650 for {
651 ln.(*TCPListener).SetDeadline(time.Now().Add(5 * time.Millisecond))
652 c, err := ln.Accept()
653 if perr := parseAcceptError(err); perr != nil {
654 t.Error(perr)
655 }
656 if err != nil {
657 if c != nil {
658 t.Errorf("Accept returned non-nil interface %T(%v) with err != nil", c, c)
659 }
660 if nerr, ok := err.(Error); !ok || (!nerr.Timeout() && !nerr.Temporary()) {
661 return
662 }
663 continue
664 }
665 c.Close()
666 }
667 }
668 ls := newLocalServer(t, "tcp")
669 if err := ls.buildup(handler); err != nil {
670 ls.teardown()
671 t.Fatal(err)
672 }
673
674 time.Sleep(100 * time.Millisecond)
675 ls.teardown()
676 }
677
678
679
680
681 func parseCommonError(nestedErr error) error {
682 if nestedErr == nil {
683 return nil
684 }
685
686 switch err := nestedErr.(type) {
687 case *OpError:
688 if err := err.isValid(); err != nil {
689 return err
690 }
691 nestedErr = err.Err
692 goto second
693 }
694 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
695
696 second:
697 if isPlatformError(nestedErr) {
698 return nil
699 }
700 switch err := nestedErr.(type) {
701 case *os.SyscallError:
702 nestedErr = err.Err
703 goto third
704 case *os.LinkError:
705 nestedErr = err.Err
706 goto third
707 case *fs.PathError:
708 nestedErr = err.Err
709 goto third
710 }
711 switch nestedErr {
712 case ErrClosed:
713 return nil
714 }
715 return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
716
717 third:
718 if isPlatformError(nestedErr) {
719 return nil
720 }
721 return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr)
722 }
723
724 func TestFileError(t *testing.T) {
725 switch runtime.GOOS {
726 case "windows":
727 t.Skipf("not supported on %s", runtime.GOOS)
728 }
729
730 f, err := os.CreateTemp("", "go-nettest")
731 if err != nil {
732 t.Fatal(err)
733 }
734 defer os.Remove(f.Name())
735 defer f.Close()
736
737 c, err := FileConn(f)
738 if err != nil {
739 if c != nil {
740 t.Errorf("FileConn returned non-nil interface %T(%v) with err != nil", c, c)
741 }
742 if perr := parseCommonError(err); perr != nil {
743 t.Error(perr)
744 }
745 } else {
746 c.Close()
747 t.Error("should fail")
748 }
749 ln, err := FileListener(f)
750 if err != nil {
751 if ln != nil {
752 t.Errorf("FileListener returned non-nil interface %T(%v) with err != nil", ln, ln)
753 }
754 if perr := parseCommonError(err); perr != nil {
755 t.Error(perr)
756 }
757 } else {
758 ln.Close()
759 t.Error("should fail")
760 }
761 pc, err := FilePacketConn(f)
762 if err != nil {
763 if pc != nil {
764 t.Errorf("FilePacketConn returned non-nil interface %T(%v) with err != nil", pc, pc)
765 }
766 if perr := parseCommonError(err); perr != nil {
767 t.Error(perr)
768 }
769 } else {
770 pc.Close()
771 t.Error("should fail")
772 }
773
774 ln = newLocalListener(t, "tcp")
775
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)
781 }
782 } else {
783 f.Close()
784 }
785 ln.Close()
786 }
787 }
788
789 func parseLookupPortError(nestedErr error) error {
790 if nestedErr == nil {
791 return nil
792 }
793
794 switch nestedErr.(type) {
795 case *AddrError, *DNSError:
796 return nil
797 case *fs.PathError:
798 return nil
799 }
800 return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr)
801 }
802
803 func TestContextError(t *testing.T) {
804 if !errors.Is(errCanceled, context.Canceled) {
805 t.Error("errCanceled is not context.Canceled")
806 }
807 if !errors.Is(errTimeout, context.DeadlineExceeded) {
808 t.Error("errTimeout is not context.DeadlineExceeded")
809 }
810 }
811
View as plain text