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