@@ -26,7 +26,7 @@ public class ChannelDbConnectionPoolTest
26
26
public ChannelDbConnectionPoolTest ( )
27
27
{
28
28
// Use a stubbed connection factory to avoid network code
29
- connectionFactory = new ConnectionFactoryStub ( ) ;
29
+ connectionFactory = new SuccessfulConnectionFactory ( ) ;
30
30
identity = DbConnectionPoolIdentity . NoIdentity ;
31
31
connectionPoolProviderInfo = new DbConnectionPoolProviderInfo ( ) ;
32
32
poolGroupOptions = new DbConnectionPoolGroupOptions (
@@ -54,20 +54,21 @@ public ChannelDbConnectionPoolTest()
54
54
[ InlineData ( 1 ) ]
55
55
[ InlineData ( 5 ) ]
56
56
[ InlineData ( 10 ) ]
57
- public async Task TestGetConnectionFromEmptyPoolSync_ShouldCreateNewConnection ( int numConnections )
57
+ public void TestGetConnectionFromEmptyPoolSync_ShouldCreateNewConnection ( int numConnections )
58
58
{
59
59
// Act
60
60
for ( int i = 0 ; i < numConnections ; i ++ )
61
61
{
62
- var internalConnection = await pool . GetInternalConnection (
62
+ DbConnectionInternal internalConnection = null ;
63
+ var completed = pool . TryGetConnection (
63
64
new SqlConnection ( ) ,
65
+ taskCompletionSource : null ,
64
66
new DbConnectionOptions ( "" , null ) ,
65
- TimeSpan . Zero ,
66
- async: false ,
67
- CancellationToken . None
67
+ out internalConnection
68
68
) ;
69
69
70
70
// Assert
71
+ Assert . True ( completed ) ;
71
72
Assert . NotNull ( internalConnection ) ;
72
73
}
73
74
@@ -85,23 +86,29 @@ public async Task TestGetConnectionFromEmptyPoolAsync_ShouldCreateNewConnection(
85
86
// Act
86
87
for ( int i = 0 ; i < numConnections ; i ++ )
87
88
{
88
- var internalConnection = await pool . GetInternalConnection (
89
+ var tcs = new TaskCompletionSource < DbConnectionInternal > ( ) ;
90
+ DbConnectionInternal internalConnection = null ;
91
+ var completed = pool . TryGetConnection (
89
92
new SqlConnection ( ) ,
93
+ tcs ,
90
94
new DbConnectionOptions ( "" , null ) ,
91
- TimeSpan . Zero ,
92
- async: false ,
93
- CancellationToken . None
95
+ out internalConnection
94
96
) ;
95
97
96
98
// Assert
97
- Assert . NotNull ( internalConnection ) ;
99
+ Assert . False ( completed ) ;
100
+ Assert . Null ( internalConnection ) ;
101
+ Assert . NotNull ( await tcs . Task ) ;
98
102
}
99
103
100
104
101
105
// Assert
102
106
Assert . Equal ( numConnections , pool . Count ) ;
103
107
}
104
108
109
+ // Test that requests to get connection from the pool fails when max pool size is reached
110
+
111
+
105
112
#region Property Tests
106
113
107
114
[ Fact ]
@@ -236,15 +243,53 @@ public void TestTransactionEnded()
236
243
{
237
244
Assert . Throws < NotImplementedException > ( ( ) => pool . TransactionEnded ( null ! , null ! ) ) ;
238
245
}
246
+ [ Fact ]
247
+ public void TestGetConnectionFailsWhenMaxPoolSizeReached ( )
248
+ {
249
+ // Arrange
250
+ for ( int i = 0 ; i < poolGroupOptions . MaxPoolSize ; i ++ )
251
+ {
252
+ DbConnectionInternal internalConnection = null ;
253
+ var completed = pool . TryGetConnection (
254
+ new SqlConnection ( ) ,
255
+ taskCompletionSource : null ,
256
+ new DbConnectionOptions ( "" , null ) ,
257
+ out internalConnection
258
+ ) ;
259
+
260
+ Assert . True ( completed ) ;
261
+ Assert . NotNull ( internalConnection ) ;
262
+ }
239
263
264
+ try
265
+ {
266
+ // Act
267
+ DbConnectionInternal extraConnection = null ;
268
+ var exceeded = pool . TryGetConnection (
269
+ //TODO: set timeout to make this faster
270
+ new SqlConnection ( ) ,
271
+ taskCompletionSource : null ,
272
+ new DbConnectionOptions ( "" , null ) ,
273
+ out extraConnection
274
+ ) ;
275
+ } catch ( Exception ex )
276
+ {
277
+ // Assert
278
+ Assert . IsType < InvalidOperationException > ( ex ) ;
279
+ Assert . Equal ( "Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached." , ex . Message ) ;
280
+ }
281
+
282
+ // Assert
283
+ Assert . Equal ( poolGroupOptions . MaxPoolSize , pool . Count ) ;
284
+ }
240
285
#endregion
241
286
242
287
#region Test classes
243
- internal class ConnectionFactoryStub : DbConnectionFactory
288
+ internal class SuccessfulConnectionFactory : DbConnectionFactory
244
289
{
245
290
protected override DbConnectionInternal CreateConnection ( DbConnectionOptions options , DbConnectionPoolKey poolKey , object poolGroupProviderInfo , IDbConnectionPool pool , DbConnection owningConnection )
246
291
{
247
- return new TestDbConnectionInternal ( ) ;
292
+ return new SuccessfulDbConnectionInternal ( ) ;
248
293
}
249
294
250
295
#region Not Implemented Members
@@ -302,7 +347,7 @@ internal override void SetInnerConnectionTo(DbConnection owningObject, DbConnect
302
347
#endregion
303
348
}
304
349
305
- internal class TestDbConnectionInternal : DbConnectionInternal
350
+ internal class SuccessfulDbConnectionInternal : DbConnectionInternal
306
351
{
307
352
#region Not Implemented Members
308
353
public override string ServerVersion => throw new NotImplementedException ( ) ;
@@ -328,6 +373,68 @@ protected override void Deactivate()
328
373
}
329
374
#endregion
330
375
}
376
+
377
+ internal class TimeoutConnectionFactory : DbConnectionFactory
378
+ {
379
+ protected override DbConnectionInternal CreateConnection ( DbConnectionOptions options , DbConnectionPoolKey poolKey , object poolGroupProviderInfo , IDbConnectionPool pool , DbConnection owningConnection )
380
+ {
381
+ return new SuccessfulDbConnectionInternal ( ) ;
382
+ }
383
+
384
+ #region Not Implemented Members
385
+ public override DbProviderFactory ProviderFactory => throw new NotImplementedException ( ) ;
386
+
387
+ protected override DbConnectionOptions CreateConnectionOptions ( string connectionString , DbConnectionOptions previous )
388
+ {
389
+ throw new NotImplementedException ( ) ;
390
+ }
391
+
392
+ protected override DbConnectionPoolGroupOptions CreateConnectionPoolGroupOptions ( DbConnectionOptions options )
393
+ {
394
+ throw new NotImplementedException ( ) ;
395
+ }
396
+
397
+ protected override int GetObjectId ( DbConnection connection )
398
+ {
399
+ throw new NotImplementedException ( ) ;
400
+ }
401
+
402
+ internal override DbConnectionPoolGroup GetConnectionPoolGroup ( DbConnection connection )
403
+ {
404
+ throw new NotImplementedException ( ) ;
405
+ }
406
+
407
+ internal override DbConnectionInternal GetInnerConnection ( DbConnection connection )
408
+ {
409
+ throw new NotImplementedException ( ) ;
410
+ }
411
+
412
+ internal override void PermissionDemand ( DbConnection outerConnection )
413
+ {
414
+ throw new NotImplementedException ( ) ;
415
+ }
416
+
417
+ internal override void SetConnectionPoolGroup ( DbConnection outerConnection , DbConnectionPoolGroup poolGroup )
418
+ {
419
+ throw new NotImplementedException ( ) ;
420
+ }
421
+
422
+ internal override void SetInnerConnectionEvent ( DbConnection owningObject , DbConnectionInternal to )
423
+ {
424
+ throw new NotImplementedException ( ) ;
425
+ }
426
+
427
+ internal override bool SetInnerConnectionFrom ( DbConnection owningObject , DbConnectionInternal to , DbConnectionInternal from )
428
+ {
429
+ throw new NotImplementedException ( ) ;
430
+ }
431
+
432
+ internal override void SetInnerConnectionTo ( DbConnection owningObject , DbConnectionInternal to )
433
+ {
434
+ throw new NotImplementedException ( ) ;
435
+ }
436
+ #endregion
437
+ }
331
438
#endregion
332
439
}
333
440
}
0 commit comments