14
14
*/
15
15
16
16
using System ;
17
+ using System . IO ;
17
18
using System . Net ;
19
+ using System . Net . Sockets ;
20
+ using System . Reflection ;
18
21
using System . Threading ;
19
22
using System . Threading . Tasks ;
20
23
using FluentAssertions ;
@@ -252,6 +255,190 @@ public void A_description_changed_event_with_a_heartbeat_exception_should_clear_
252
255
253
256
_mockConnectionPool. Verify ( p => p . Clear ( ) , Times . Once ) ;
254
257
}
258
+
259
+ [ Theory ]
260
+ [ InlineData ( ( ServerErrorCode ) ( - 1 ) , false ) ]
261
+ [ InlineData ( ServerErrorCode . NotMaster , true ) ]
262
+ [ InlineData ( ServerErrorCode . NotMasterNoSlaveOk , true ) ]
263
+ [ InlineData ( ServerErrorCode . NotMasterOrSecondary , false ) ]
264
+ internal void IsNotMaster_should_return_expected_result_for_code( ServerErrorCode code , bool expectedResult )
265
+ {
266
+ _subject. Initialize ( ) ;
267
+
268
+ var result = _subject. IsNotMaster ( code , null ) ;
269
+
270
+ result. Should ( ) . Be ( expectedResult ) ;
271
+ if ( result )
272
+ {
273
+ _subject. IsRecovering ( code , null ) . Should ( ) . BeFalse ( ) ;
274
+ }
275
+ }
276
+
277
+ [ Theory ]
278
+ [ InlineData ( null , false ) ]
279
+ [ InlineData ( "abc" , false ) ]
280
+ [ InlineData ( "not master" , true ) ]
281
+ [ InlineData ( "not master or secondary" , false ) ]
282
+ internal void IsNotMaster_should_return_expected_result_for_message( string message , bool expectedResult )
283
+ {
284
+ _subject. Initialize ( ) ;
285
+
286
+ var result = _subject. IsNotMaster ( ( ServerErrorCode ) ( - 1 ) , message ) ;
287
+
288
+ result. Should ( ) . Be ( expectedResult ) ;
289
+ if ( result )
290
+ {
291
+ _subject. IsRecovering ( ( ServerErrorCode ) ( - 1 ) , message ) . Should ( ) . BeFalse ( ) ;
292
+ }
293
+ }
294
+
295
+ [ Theory ]
296
+ [ InlineData ( ( ServerErrorCode ) ( - 1 ) , false ) ]
297
+ [ InlineData ( ServerErrorCode . NotMaster , true ) ]
298
+ [ InlineData ( ServerErrorCode . InterruptedAtShutdown , true ) ]
299
+ internal void IsNotMasterOrRecovering_should_return_expected_result( ServerErrorCode code , bool expectedResult )
300
+ {
301
+ _subject. Initialize ( ) ;
302
+
303
+ var result = _subject. IsNotMasterOrRecovering ( code , null ) ;
304
+
305
+ result. Should ( ) . Be ( expectedResult ) ;
306
+ }
307
+
308
+ [ Theory ]
309
+ [ InlineData ( ( ServerErrorCode ) ( - 1 ) , false ) ]
310
+ [ InlineData ( ServerErrorCode . InterruptedAtShutdown , true ) ]
311
+ [ InlineData ( ServerErrorCode . InterruptedDueToReplStateChange , true ) ]
312
+ [ InlineData ( ServerErrorCode . NotMasterOrSecondary , true ) ]
313
+ [ InlineData ( ServerErrorCode . PrimarySteppedDown , true ) ]
314
+ [ InlineData ( ServerErrorCode . ShutdownInProgress , true ) ]
315
+ internal void IsRecovering_should_return_expected_result_for_code( ServerErrorCode code , bool expectedResult )
316
+ {
317
+ _subject. Initialize ( ) ;
318
+
319
+ var result = _subject. IsRecovering ( code , null ) ;
320
+
321
+ result. Should ( ) . Be ( expectedResult ) ;
322
+ if ( result )
323
+ {
324
+ _subject. IsNotMaster ( code , null ) . Should ( ) . BeFalse ( ) ;
325
+ }
326
+ }
327
+
328
+ [ Theory ]
329
+ [ InlineData ( null , false ) ]
330
+ [ InlineData ( "abc" , false ) ]
331
+ [ InlineData ( "node is recovering" , true ) ]
332
+ [ InlineData ( "not master or secondary" , true ) ]
333
+ internal void IsRecovering_should_return_expected_result_for_message( string message , bool expectedResult )
334
+ {
335
+ _subject. Initialize ( ) ;
336
+
337
+ var result = _subject. IsRecovering ( ( ServerErrorCode ) ( - 1 ) , message ) ;
338
+
339
+ result. Should ( ) . Be ( expectedResult ) ;
340
+ if ( result )
341
+ {
342
+ _subject. IsNotMaster ( ( ServerErrorCode ) ( - 1 ) , message ) . Should ( ) . BeFalse ( ) ;
343
+ }
344
+ }
345
+
346
+ [ Theory ]
347
+ [ InlineData ( nameof ( EndOfStreamException ) , true ) ]
348
+ [ InlineData ( nameof ( Exception ) , false ) ]
349
+ [ InlineData ( nameof ( IOException ) , true ) ]
350
+ [ InlineData ( nameof ( MongoConnectionException ) , true ) ]
351
+ [ InlineData ( nameof ( MongoNodeIsRecoveringException ) , true ) ]
352
+ [ InlineData ( nameof ( MongoNotPrimaryException ) , true ) ]
353
+ [ InlineData ( nameof ( SocketException ) , true ) ]
354
+ internal void ShouldInvalidateServer_should_return_expected_result_for_exceptionType( string exceptionTypeName , bool expectedResult )
355
+ {
356
+ _subject. Initialize ( ) ;
357
+ Exception exception;
358
+ var clusterId = new ClusterId( 1 ) ;
359
+ var serverId = new ServerId( clusterId , new DnsEndPoint ( "localhost" , 27017 ) ) ;
360
+ var connectionId = new ConnectionId( serverId ) ;
361
+ var command = new BsonDocument( "command" , 1 ) ;
362
+ var commandResult = new BsonDocument( "ok" , 1 ) ;
363
+ switch ( exceptionTypeName )
364
+ {
365
+ case nameof( EndOfStreamException ) : exception = new EndOfStreamException( ) ; break ;
366
+ case nameof( Exception ) : exception = new Exception( ) ; break ;
367
+ case nameof( IOException ) : exception = new IOException( ) ; break ;
368
+ case nameof( MongoConnectionException ) : exception = new MongoConnectionException( connectionId , "message" ) ; break ;
369
+ case nameof( MongoNodeIsRecoveringException ) : exception = new MongoNodeIsRecoveringException( connectionId , command , commandResult ) ; break ;
370
+ case nameof( MongoNotPrimaryException ) : exception = new MongoNotPrimaryException( connectionId , command , commandResult ) ; break ;
371
+ case nameof( SocketException ) : exception = new SocketException( ) ; break ;
372
+ default : throw new Exception( $ "Invalid exceptionTypeName: { exceptionTypeName } .") ;
373
+ }
374
+
375
+ var result = _subject. ShouldInvalidateServer ( exception ) ;
376
+
377
+ result. Should ( ) . Be ( expectedResult ) ;
378
+ }
379
+
380
+ [ Theory ]
381
+ [ InlineData ( null , null , false ) ]
382
+ [ InlineData ( ( ServerErrorCode ) ( - 1 ) , null , false ) ]
383
+ [ InlineData ( ServerErrorCode . NotMaster , null , true ) ]
384
+ [ InlineData ( ServerErrorCode . InterruptedAtShutdown , null , true ) ]
385
+ [ InlineData ( null , "abc" , false ) ]
386
+ [ InlineData ( null , "not master" , true ) ]
387
+ [ InlineData ( null , "not master or secondary" , true ) ]
388
+ [ InlineData ( null , "node is recovering" , true ) ]
389
+ internal void ShouldInvalidateServer_should_return_expected_result_for_MongoCommandException( ServerErrorCode ? code , string message , bool expectedResult )
390
+ {
391
+ _subject. Initialize ( ) ;
392
+ var clusterId = new ClusterId( 1 ) ;
393
+ var serverId = new ServerId( clusterId , new DnsEndPoint ( "localhost" , 27017 ) ) ;
394
+ var connectionId = new ConnectionId( serverId ) ;
395
+ var command = new BsonDocument( "command" , 1 ) ;
396
+ var commandResult = new BsonDocument
397
+ {
398
+ { "ok", 0 } ,
399
+ { "code" , ( ) => ( int ) code . Value , code . HasValue } ,
400
+ { "errmsg" , message , message != null }
401
+ } ;
402
+ var exception = new MongoCommandException( connectionId , "message" , command , commandResult ) ;
403
+
404
+ var result = _subject. ShouldInvalidateServer ( exception ) ;
405
+
406
+ result. Should ( ) . Be ( expectedResult ) ;
407
+ }
408
+
409
+ [ Theory ]
410
+ [ InlineData ( null , null , false ) ]
411
+ [ InlineData ( ( ServerErrorCode ) ( - 1 ) , null , false ) ]
412
+ [ InlineData ( ServerErrorCode . NotMaster , null , true ) ]
413
+ [ InlineData ( ServerErrorCode . InterruptedAtShutdown , null , true ) ]
414
+ [ InlineData ( null , "abc" , false ) ]
415
+ [ InlineData ( null , "not master" , true ) ]
416
+ [ InlineData ( null , "not master or secondary" , true ) ]
417
+ [ InlineData ( null , "node is recovering" , true ) ]
418
+ internal void ShouldInvalidateServer_should_return_expected_result_for_MongoWriteConcernException( ServerErrorCode ? code , string message , bool expectedResult )
419
+ {
420
+ _subject. Initialize ( ) ;
421
+ var clusterId = new ClusterId( 1 ) ;
422
+ var serverId = new ServerId( clusterId , new DnsEndPoint ( "localhost" , 27017 ) ) ;
423
+ var connectionId = new ConnectionId( serverId ) ;
424
+ var command = new BsonDocument( "command" , 1 ) ;
425
+ var commandResult = new BsonDocument
426
+ {
427
+ { "ok", 1 } ,
428
+ { "writeConcernError" , new BsonDocument
429
+ {
430
+ { "code" , ( ) => ( int ) code . Value , code . HasValue } ,
431
+ { "errmsg" , message , message != null }
432
+ }
433
+ }
434
+ } ;
435
+ var writeConcernResult = new WriteConcernResult( commandResult ) ;
436
+ var exception = new MongoWriteConcernException( connectionId , "message" , writeConcernResult ) ;
437
+
438
+ var result = _subject. ShouldInvalidateServer ( exception ) ;
439
+
440
+ result. Should ( ) . Be ( expectedResult ) ;
441
+ }
255
442
}
256
443
257
444
public class ServerChannelTests
@@ -346,4 +533,31 @@ public void Command_should_update_the_session_and_cluster_cluster_times()
346
533
}
347
534
}
348
535
}
536
+
537
+ internal static class ServerReflector
538
+ {
539
+ public static bool IsNotMaster ( this Server server , ServerErrorCode code , string message )
540
+ {
541
+ var methodInfo = typeof ( Server ) . GetMethod ( nameof ( IsNotMaster ) , BindingFlags . NonPublic | BindingFlags . Instance ) ;
542
+ return ( bool ) methodInfo . Invoke ( server , new object [ ] { code , message } ) ;
543
+ }
544
+
545
+ public static bool IsNotMasterOrRecovering ( this Server server , ServerErrorCode code , string message )
546
+ {
547
+ var methodInfo = typeof ( Server ) . GetMethod ( nameof ( IsNotMasterOrRecovering ) , BindingFlags . NonPublic | BindingFlags . Instance ) ;
548
+ return ( bool ) methodInfo . Invoke ( server , new object [ ] { code , message } ) ;
549
+ }
550
+
551
+ public static bool IsRecovering ( this Server server , ServerErrorCode code , string message )
552
+ {
553
+ var methodInfo = typeof ( Server ) . GetMethod ( nameof ( IsRecovering ) , BindingFlags . NonPublic | BindingFlags . Instance ) ;
554
+ return ( bool ) methodInfo . Invoke ( server , new object [ ] { code , message } ) ;
555
+ }
556
+
557
+ public static bool ShouldInvalidateServer ( this Server server , Exception exception )
558
+ {
559
+ var methodInfo = typeof ( Server ) . GetMethod ( nameof ( ShouldInvalidateServer ) , BindingFlags . NonPublic | BindingFlags . Instance ) ;
560
+ return ( bool ) methodInfo . Invoke ( server , new object [ ] { exception } ) ;
561
+ }
562
+ }
349
563
}
0 commit comments