Source file
src/net/dial_unix_test.go
1
2
3
4
5
6
7 package net
8
9 import (
10 "context"
11 "errors"
12 "syscall"
13 "testing"
14 "time"
15 )
16
17 func init() {
18 isEADDRINUSE = func(err error) bool {
19 return errors.Is(err, syscall.EADDRINUSE)
20 }
21 }
22
23
24 func TestDialContextCancelRace(t *testing.T) {
25 oldConnectFunc := connectFunc
26 oldGetsockoptIntFunc := getsockoptIntFunc
27 oldTestHookCanceledDial := testHookCanceledDial
28 defer func() {
29 connectFunc = oldConnectFunc
30 getsockoptIntFunc = oldGetsockoptIntFunc
31 testHookCanceledDial = oldTestHookCanceledDial
32 }()
33
34 ln := newLocalListener(t, "tcp")
35 listenerDone := make(chan struct{})
36 go func() {
37 defer close(listenerDone)
38 c, err := ln.Accept()
39 if err == nil {
40 c.Close()
41 }
42 }()
43 defer func() { <-listenerDone }()
44 defer ln.Close()
45
46 sawCancel := make(chan bool, 1)
47 testHookCanceledDial = func() {
48 sawCancel <- true
49 }
50
51 ctx, cancelCtx := context.WithCancel(context.Background())
52
53 connectFunc = func(fd int, addr syscall.Sockaddr) error {
54 err := oldConnectFunc(fd, addr)
55 t.Logf("connect(%d, addr) = %v", fd, err)
56 if err == nil {
57
58
59
60
61
62
63
64 return syscall.EINPROGRESS
65 }
66 return err
67 }
68
69 getsockoptIntFunc = func(fd, level, opt int) (val int, err error) {
70 val, err = oldGetsockoptIntFunc(fd, level, opt)
71 t.Logf("getsockoptIntFunc(%d, %d, %d) = (%v, %v)", fd, level, opt, val, err)
72 if level == syscall.SOL_SOCKET && opt == syscall.SO_ERROR && err == nil && val == 0 {
73 t.Logf("canceling context")
74
75
76
77 cancelCtx()
78
79
80
81
82 select {
83 case <-sawCancel:
84 t.Logf("saw cancel")
85 case <-time.After(5 * time.Second):
86 t.Errorf("didn't see cancel after 5 seconds")
87 }
88 }
89 return
90 }
91
92 var d Dialer
93 c, err := d.DialContext(ctx, "tcp", ln.Addr().String())
94 if err == nil {
95 c.Close()
96 t.Fatal("unexpected successful dial; want context canceled error")
97 }
98
99 select {
100 case <-ctx.Done():
101 case <-time.After(5 * time.Second):
102 t.Fatal("expected context to be canceled")
103 }
104
105 oe, ok := err.(*OpError)
106 if !ok || oe.Op != "dial" {
107 t.Fatalf("Dial error = %#v; want dial *OpError", err)
108 }
109
110 if oe.Err != errCanceled {
111 t.Errorf("DialContext = (%v, %v); want OpError with error %v", c, err, errCanceled)
112 }
113 }
114
View as plain text