@@ -41,7 +41,6 @@ namespace MongoDB.Driver.Core.Tests.Jira
41
41
{
42
42
public class CSharp3173Tests
43
43
{
44
- #if WINDOWS
45
44
#pragma warning disable CS0618 // Type or member is obsolete
46
45
private readonly static ClusterConnectionMode __clusterConnectionMode = ClusterConnectionMode . Sharded ;
47
46
private readonly static ConnectionModeSwitch __connectionModeSwitch = ConnectionModeSwitch . UseConnectionMode ;
@@ -93,7 +92,7 @@ public void Ensure_command_network_error_before_hadnshake_is_correctly_handled([
93
92
}
94
93
95
94
var e = exception . Should ( ) . BeOfType < MongoConnectionException > ( ) . Subject ;
96
- e. Message . Should ( ) . Be ( "DnsException" ) ;
95
+ e. Message . Should ( ) . Be ( "DnsException:pool " ) ;
97
96
98
97
// 2. Waiting for the hello or legacy hello check
99
98
hasNetworkErrorBeenTriggered . SetResult ( true ) ; // unlock the in-progress hello or legacy hello response
@@ -129,22 +128,23 @@ public void Ensure_command_network_error_before_hadnshake_is_correctly_handled([
129
128
AssertEvent ( initialHeartbeatEvents [ 1 ] , __endPoint2 , ServerType . ShardRouter , "Heartbeat" ) ; // the next 27018 events will be suppressed
130
129
131
130
AssertNextEvent ( eventCapturer , initialSelectedEndpoint , ServerType . Unknown , "InvalidatedBecause:ChannelException during handshake: MongoDB.Driver.MongoConnectionException: DnsException" ) ;
132
- AssertNextEvent ( eventCapturer , initialSelectedEndpoint , ServerType . Unknown , "Heartbeat" , typeof ( MongoConnectionException ) ) ;
131
+ AssertNextEvent ( eventCapturer , initialSelectedEndpoint , ServerType . Unknown , "Heartbeat" , ( typeof ( MongoConnectionException ) , "DnsException:sdam" ) ) ;
133
132
eventCapturer . Any ( ) . Should ( ) . BeFalse ( ) ;
134
133
135
134
int GetPort ( EndPoint endpoint ) => ( ( DnsEndPoint ) endpoint ) . Port ;
136
135
}
137
136
138
137
// private method
139
- private void AssertEvent ( ServerDescriptionChangedEvent @event , EndPoint expectedEndPoint , ServerType expectedServerType , string expectedReasonStart , Type exceptionType = null )
138
+ private void AssertEvent ( ServerDescriptionChangedEvent @event , EndPoint expectedEndPoint , ServerType expectedServerType , string expectedReasonStart , ( Type ExceptionType , string ExceptionMessage ) ? exceptionInfo = null )
140
139
{
141
140
@event . ServerId . ClusterId . Should ( ) . Be ( __clusterId ) ;
142
141
@event . NewDescription . EndPoint . Should ( ) . Be ( expectedEndPoint ) ;
143
142
@event . NewDescription . Type . Should ( ) . Be ( expectedServerType ) ;
144
143
@event . NewDescription . State . Should ( ) . Be ( expectedServerType == ServerType . Unknown ? ServerState . Disconnected : ServerState . Connected ) ;
145
- if ( exceptionType != null )
144
+ if ( exceptionInfo . HasValue )
146
145
{
147
- @event . NewDescription . HeartbeatException . Should ( ) . BeOfType ( exceptionType ) ;
146
+ @event . NewDescription . HeartbeatException . Should ( ) . BeOfType ( exceptionInfo . Value . ExceptionType ) ;
147
+ @event . NewDescription . HeartbeatException . Message . Should ( ) . Be ( exceptionInfo . Value . ExceptionMessage ) ;
148
148
}
149
149
else
150
150
{
@@ -153,10 +153,10 @@ private void AssertEvent(ServerDescriptionChangedEvent @event, EndPoint expected
153
153
@event . NewDescription . ReasonChanged . Should ( ) . StartWith ( expectedReasonStart ) ;
154
154
}
155
155
156
- private void AssertNextEvent ( EventCapturer eventCapturer , EndPoint expectedEndPoint , ServerType expectedServerType , string expectedReasonStart , Type exceptionType = null )
156
+ private void AssertNextEvent ( EventCapturer eventCapturer , EndPoint expectedEndPoint , ServerType expectedServerType , string expectedReasonStart , ( Type ExceptionType , string ExceptionMessage ) ? exceptionInfo = null )
157
157
{
158
158
var @event = eventCapturer . Next ( ) . Should ( ) . BeOfType < ServerDescriptionChangedEvent > ( ) . Subject ;
159
- AssertEvent ( @event , expectedEndPoint , expectedServerType , expectedReasonStart , exceptionType ) ;
159
+ AssertEvent ( @event , expectedEndPoint , expectedServerType , expectedReasonStart , exceptionInfo ) ;
160
160
}
161
161
162
162
private IConnectionPoolFactory CreateAndSetupConnectionPoolFactory ( Func < ServerId , IConnectionExceptionHandler > exceptionHandlerProvider , params ( ServerId ServerId , EndPoint Endpoint , bool IsHealthy ) [ ] serverInfoCollection )
@@ -183,7 +183,7 @@ void SetupConnection(Mock<IConnectionHandle> mockConnectionHandle, ServerId serv
183
183
184
184
void SetupConnectionPool ( Mock < IConnectionPool > mockConnectionPool , IConnectionHandle connection , Func < IConnectionExceptionHandler > exceptionHandlerProvider )
185
185
{
186
- var dnsException = CreateDnsException ( connection . ConnectionId ) ;
186
+ var dnsException = CreateDnsException ( connection . ConnectionId , from : "pool" ) ;
187
187
mockConnectionPool
188
188
. Setup ( c => c . AcquireConnection ( It . IsAny < CancellationToken > ( ) ) )
189
189
. Callback ( ( ) => exceptionHandlerProvider ( ) . HandleExceptionOnOpen ( dnsException ) )
@@ -210,17 +210,33 @@ private IConnectionFactory CreateAndSetupServerMonitorConnectionFactory(
210
210
211
211
foreach ( var serverInfo in serverInfoCollection )
212
212
{
213
+ // configure ServerMonitor connections
213
214
var mockServerMonitorConnection = new Mock < IConnection > ( ) ;
214
215
SetupServerMonitorConnection ( mockServerMonitorConnection , serverInfo . ServerId , serverInfo . IsHealthy , hasNetworkErrorBeenTriggered , hasClusterBeenDisposed , streamable ) ;
215
216
mockConnectionFactory
217
+ . When ( ( ) => ! Environment . StackTrace . Contains ( nameof ( RoundTripTimeMonitor ) ) )
216
218
. Setup ( c => c . CreateConnection ( serverInfo . ServerId , serverInfo . Endpoint ) )
217
219
. Returns ( mockServerMonitorConnection . Object ) ;
220
+
221
+ // configure healthy RTT connections
222
+ var mockRttConnection = new Mock < IConnection > ( ) ;
223
+ SetupServerMonitorConnection (
224
+ mockRttConnection ,
225
+ serverInfo . ServerId ,
226
+ isHealthy : true ,
227
+ hasNetworkErrorBeenTriggered : null , // has no role for RTT
228
+ hasClusterBeenDisposed ,
229
+ streamable ) ;
230
+ mockConnectionFactory
231
+ . When ( ( ) => Environment . StackTrace . Contains ( nameof ( RoundTripTimeMonitor ) ) )
232
+ . Setup ( c => c . CreateConnection ( serverInfo . ServerId , serverInfo . Endpoint ) )
233
+ . Returns ( mockRttConnection . Object ) ;
218
234
}
219
235
220
236
return mockConnectionFactory . Object ;
221
237
}
222
238
223
- private MultiServerCluster CreateAndSetupCluster ( TaskCompletionSource < bool > hasNetworkErrorBeenTriggered , TaskCompletionSource < bool > hasClusterBeenDisposed , EventCapturer eventCapturer , bool streamable )
239
+ private MultiServerCluster CreateAndSetupCluster ( TaskCompletionSource < bool > hasNetworkErrorBeenTriggered , TaskCompletionSource < bool > hasClusterBeenDisposed , IEventSubscriber eventCapturer , bool streamable )
224
240
{
225
241
( ServerId ServerId , EndPoint Endpoint , bool IsHealthy ) [ ] serverInfoCollection = new [ ]
226
242
{
@@ -253,9 +269,9 @@ private MultiServerCluster CreateAndSetupCluster(TaskCompletionSource<bool> hasN
253
269
return cluster = new MultiServerCluster ( clusterSettings , serverFactory , eventCapturer ) ;
254
270
}
255
271
256
- private Exception CreateDnsException ( ConnectionId connectionId )
272
+ private Exception CreateDnsException ( ConnectionId connectionId , string from )
257
273
{
258
- return new MongoConnectionException ( connectionId , "DnsException" ) ;
274
+ return new MongoConnectionException ( connectionId , $ "DnsException: { from } ") ;
259
275
}
260
276
261
277
private IServerSelector CreateWritableServerAndEndPointSelector ( EndPoint endPoint )
@@ -325,12 +341,13 @@ private void SetupServerMonitorConnection(
325
341
326
342
void SetupFailedConnection ( Mock < IConnection > mockFaultyConnection )
327
343
{
344
+ Ensure . IsNotNull ( hasNetworkErrorBeenTriggered , nameof ( hasNetworkErrorBeenTriggered ) ) ;
345
+
328
346
// async path is not used in serverMonitor
329
347
var faultyConnectionResponses = new Queue < Action > ( new Action [ ]
330
348
{
331
- ( ) => { /* no action needed*/ } , // the first hello or legacy hello configuration passes
332
- ( ) => { /* no action needed*/ } , // RTT
333
- ( ) => throw CreateDnsException ( mockConnection . Object . ConnectionId ) , // the dns exception. Should be triggered after Invalidate
349
+ ( ) => { } , // the first hello or legacy hello configuration passes
350
+ ( ) => throw CreateDnsException ( mockConnection . Object . ConnectionId , from : "sdam" ) , // the dns exception. Should be triggered after Invalidate
334
351
( ) => WaitForTaskOrTimeout ( hasClusterBeenDisposed . Task , TimeSpan . FromMinutes ( 1 ) , "cluster dispose" )
335
352
} ) ;
336
353
mockFaultyConnection
@@ -345,8 +362,10 @@ void SetupFailedConnection(Mock<IConnection> mockFaultyConnection)
345
362
. Setup ( c => c . ReceiveMessage ( It . IsAny < int > ( ) , It . IsAny < IMessageEncoderSelector > ( ) , It . IsAny < MessageEncoderSettings > ( ) , It . IsAny < CancellationToken > ( ) ) )
346
363
. Returns ( ( ) =>
347
364
{
348
- // wait until the command network error has been triggered
349
- WaitForTaskOrTimeout ( hasNetworkErrorBeenTriggered . Task , TimeSpan . FromMinutes ( 1 ) , "network error" ) ;
365
+ WaitForTaskOrTimeout (
366
+ hasNetworkErrorBeenTriggered . Task ,
367
+ TimeSpan . FromMinutes ( 1 ) ,
368
+ testTarget : "network error" ) ;
350
369
return commandResponseAction ( ) ;
351
370
} ) ;
352
371
}
@@ -372,6 +391,5 @@ private void WaitForTaskOrTimeout(Task task, TimeSpan timeout, string testTarget
372
391
throw new Exception ( $ "The waiting for { testTarget } is exceeded timeout { timeout } .") ;
373
392
}
374
393
}
375
- #endif
376
394
}
377
395
}
0 commit comments