@@ -57,109 +57,89 @@ func (cncd *channelNetConnDialer) DialContext(_ context.Context, _, _ string) (n
57
57
func TestServerConnectionTimeout (t * testing.T ) {
58
58
testCases := []struct {
59
59
desc string
60
- ctxFn func () (context.Context , context.CancelFunc )
61
60
dialer func (Dialer ) Dialer
62
61
handshaker func (Handshaker ) Handshaker
62
+ operationTimeout time.Duration
63
+ connectTimeout time.Duration
63
64
expectErr bool
64
65
expectPoolCleared bool
65
66
}{
66
67
{
67
- desc : "No errors should not clear the pool" ,
68
- ctxFn : func () (context.Context , context.CancelFunc ) {
69
- return context .Background (), nil
70
- },
68
+ desc : "successful connection should not clear the pool" ,
71
69
expectErr : false ,
72
70
expectPoolCleared : false ,
73
71
},
74
72
{
75
- desc : "Parent context deadline exceeded error during dialing should not clear the pool" ,
76
- ctxFn : func () (context.Context , context.CancelFunc ) {
77
- return context .WithTimeout (context .Background (), 100 * time .Millisecond )
78
- },
73
+ desc : "operation timeout error during dialing should not clear the pool" ,
79
74
dialer : func (Dialer ) Dialer {
80
75
var d net.Dialer
81
76
return DialerFunc (func (ctx context.Context , network , addr string ) (net.Conn , error ) {
82
- // Sleep for at least 150ms and expect the context passed to server.Connection()
83
- // to time out during the sleep. Expect the error returned by DialContext() to
84
- // be treated as a timeout caused by an operation-scoped deadline.
77
+ // Wait for the passed in context to time out. Expect the error returned by
78
+ // DialContext() to be treated as a timeout caused by an operation-scoped deadline.
85
79
// E.g. FindOne(context.WithTimeout(...))
86
- time . Sleep ( 150 * time . Millisecond )
80
+ <- ctx . Done ( )
87
81
return d .DialContext (ctx , network , addr )
88
82
})
89
83
},
84
+ operationTimeout : 100 * time .Millisecond ,
85
+ connectTimeout : 1 * time .Minute ,
90
86
expectErr : true ,
91
87
expectPoolCleared : false ,
92
88
},
93
89
{
94
- desc : "Child context deadline exceeded error during dialing should clear the pool" ,
95
- ctxFn : func () (context.Context , context.CancelFunc ) {
96
- // Return a context with a timeout that will not be reached during the test.
97
- return context .WithTimeout (context .Background (), 1 * time .Minute )
98
- },
90
+ desc : "connectTimeMS timeout error during dialing should clear the pool" ,
99
91
dialer : func (Dialer ) Dialer {
100
92
var d net.Dialer
101
93
return DialerFunc (func (ctx context.Context , network , addr string ) (net.Conn , error ) {
102
- // Wrap the context in a context with an already-exceeded deadline. Expect the
103
- // error returned by DialContext() to be treated as a timeout caused by reaching
104
- // connectTimeoutMS.
105
- ctx , cancel := context .WithDeadline (ctx , time .Now ().Add (- 1 * time .Hour ))
106
- defer cancel ()
94
+ // Wait for the passed in context to time out. Expect the error returned by
95
+ // DialContext() to be treated as a timeout caused by reaching connectTimeoutMS.
96
+ <- ctx .Done ()
107
97
return d .DialContext (ctx , network , addr )
108
98
})
109
99
},
100
+ operationTimeout : 1 * time .Minute ,
101
+ connectTimeout : 100 * time .Millisecond ,
110
102
expectErr : true ,
111
103
expectPoolCleared : true ,
112
104
},
113
105
{
114
- desc : "Parent context deadline exceeded error during handshake should not clear the pool" ,
115
- ctxFn : func () (context.Context , context.CancelFunc ) {
116
- return context .WithTimeout (context .Background (), 100 * time .Millisecond )
117
- },
118
- handshaker : func (Handshaker ) Handshaker {
119
- h := auth .Handshaker (nil , & auth.HandshakeOptions {})
120
- return & testHandshaker {
121
- getHandshakeInformation : func (ctx context.Context , addr address.Address , c driver.Connection ) (driver.HandshakeInformation , error ) {
122
- // Sleep for at least 150ms and expect the context passed to
123
- // server.Connection() to time out during the sleep. Expect the error
124
- // returned by GetHandshakeInformation() to be treated as a timeout caused
125
- // by an operation-scoped deadline.
126
- // E.g. FindOne(context.WithTimeout(...))
127
- time .Sleep (150 * time .Millisecond )
128
- return h .GetHandshakeInformation (ctx , addr , c )
129
- },
130
- }
106
+ desc : "connectTimeMS timeout error during dialing with no operation timeout should clear the pool" ,
107
+ dialer : func (Dialer ) Dialer {
108
+ var d net.Dialer
109
+ return DialerFunc (func (ctx context.Context , network , addr string ) (net.Conn , error ) {
110
+ // Wait for the passed in context to time out. Expect the error returned by
111
+ // DialContext() to be treated as a timeout caused by reaching connectTimeoutMS.
112
+ <- ctx .Done ()
113
+ return d .DialContext (ctx , network , addr )
114
+ })
131
115
},
116
+ operationTimeout : 0 , // Uses a context.Background() with no timeout.
117
+ connectTimeout : 100 * time .Millisecond ,
132
118
expectErr : true ,
133
- expectPoolCleared : false ,
119
+ expectPoolCleared : true ,
134
120
},
135
121
{
136
- desc : "Child context deadline exceeded error during handshake should clear the pool" ,
137
- ctxFn : func () (context.Context , context.CancelFunc ) {
138
- // Return a context with a timeout that will not be reached during the test.
139
- return context .WithTimeout (context .Background (), 1 * time .Minute )
140
- },
122
+ desc : "operation timeout error during handshake should not clear the pool" ,
141
123
handshaker : func (Handshaker ) Handshaker {
142
124
h := auth .Handshaker (nil , & auth.HandshakeOptions {})
143
125
return & testHandshaker {
144
126
getHandshakeInformation : func (ctx context.Context , addr address.Address , c driver.Connection ) (driver.HandshakeInformation , error ) {
145
- // Wrap the context in a context with an already-exceeded deadline . Expect
146
- // the error returned by GetHandshakeInformation() to be treated as a
147
- // timeout caused by connectTimeoutMS .
148
- ctx , cancel := context .WithDeadline ( ctx , time . Now (). Add ( - 1 * time . Hour ))
149
- defer cancel ()
127
+ // Wait for the passed in context to time out . Expect the error returned by
128
+ // GetHandshakeInformation() to be treated as a timeout caused by an
129
+ // operation-scoped deadline .
130
+ // E.g. FindOne( context.WithTimeout(... ))
131
+ <- ctx . Done ()
150
132
return h .GetHandshakeInformation (ctx , addr , c )
151
133
},
152
134
}
153
135
},
136
+ operationTimeout : 100 * time .Millisecond ,
137
+ connectTimeout : 1 * time .Minute ,
154
138
expectErr : true ,
155
- expectPoolCleared : true ,
139
+ expectPoolCleared : false ,
156
140
},
157
141
{
158
- desc : "Dial errors unrelated to context timeouts should clear the pool" ,
159
- ctxFn : func () (context.Context , context.CancelFunc ) {
160
- // Return a context with a timeout that will not be reached during the test.
161
- return context .WithTimeout (context .Background (), 1 * time .Minute )
162
- },
142
+ desc : "dial errors unrelated to context timeouts should clear the pool" ,
163
143
dialer : func (Dialer ) Dialer {
164
144
var d net.Dialer
165
145
return DialerFunc (func (ctx context.Context , _ , _ string ) (net.Conn , error ) {
@@ -171,22 +151,19 @@ func TestServerConnectionTimeout(t *testing.T) {
171
151
expectPoolCleared : true ,
172
152
},
173
153
{
174
- desc : "Context error with a dial error unrelated to context timeouts should clear the pool" ,
175
- ctxFn : func () (context.Context , context.CancelFunc ) {
176
- return context .WithTimeout (context .Background (), 100 * time .Millisecond )
177
- },
154
+ desc : "context error with dial errors unrelated to context timeouts should clear the pool" ,
178
155
dialer : func (Dialer ) Dialer {
179
156
var d net.Dialer
180
157
return DialerFunc (func (ctx context.Context , _ , _ string ) (net.Conn , error ) {
181
158
// Try to dial an invalid TCP address and expect an error.
182
159
c , err := d .DialContext (ctx , "tcp" , "300.0.0.0:nope" )
183
- // Sleep for at least 150ms and expect the context passed to server.Connection()
184
- // to time out during the sleep. Expect that the context error is ignored
185
- // because the dial error is not a timeout.
186
- time .Sleep (150 * time .Millisecond )
160
+ // Wait for the passed in context to time out. Expect that the context error is
161
+ // ignored because the dial error is not a timeout.
162
+ <- ctx .Done ()
187
163
return c , err
188
164
})
189
165
},
166
+ operationTimeout : 100 * time .Millisecond ,
190
167
expectErr : true ,
191
168
expectPoolCleared : true ,
192
169
},
@@ -205,10 +182,10 @@ func TestServerConnectionTimeout(t *testing.T) {
205
182
var eventsWg sync.WaitGroup
206
183
eventsWg .Add (1 )
207
184
go func () {
185
+ defer eventsWg .Done ()
208
186
for evt := range eventsCh {
209
187
events = append (events , evt )
210
188
}
211
- eventsWg .Done ()
212
189
}()
213
190
214
191
// Create a TCP listener on a random port. The listener will accept connections but not
@@ -234,6 +211,9 @@ func TestServerConnectionTimeout(t *testing.T) {
234
211
// Replace the default dialer and handshaker with the test dialer and handshaker, if
235
212
// present.
236
213
WithConnectionOptions (func (opts ... ConnectionOption ) []ConnectionOption {
214
+ if tc .connectTimeout > 0 {
215
+ opts = append (opts , WithConnectTimeout (func (time.Duration ) time.Duration { return tc .connectTimeout }))
216
+ }
237
217
if tc .dialer != nil {
238
218
opts = append (opts , WithDialer (tc .dialer ))
239
219
}
@@ -249,9 +229,11 @@ func TestServerConnectionTimeout(t *testing.T) {
249
229
require .NoError (t , err )
250
230
require .NoError (t , server .Connect (nil ))
251
231
252
- // Use the context returned by the test case ctxFn to call Connection.
253
- ctx , cancel := tc .ctxFn ()
254
- if cancel != nil {
232
+ // Create a context with the operation timeout if one is specified in the test case.
233
+ ctx := context .Background ()
234
+ if tc .operationTimeout > 0 {
235
+ var cancel context.CancelFunc
236
+ ctx , cancel = context .WithTimeout (ctx , tc .operationTimeout )
255
237
defer cancel ()
256
238
}
257
239
_ , err = server .Connection (ctx )
@@ -263,6 +245,7 @@ func TestServerConnectionTimeout(t *testing.T) {
263
245
264
246
// Close the events channel and expect that no more events are sent on the channel. Then
265
247
// wait for the events channel loop to return before inspecting the events slice.
248
+ server .Disconnect (context .Background ())
266
249
close (eventsCh )
267
250
eventsWg .Wait ()
268
251
require .NotEmpty (t , events , "expected more than 0 connection pool monitor events" )
0 commit comments