@@ -370,33 +370,111 @@ def cancel(self):
370
370
371
371
372
372
class TestResumableBidiRpc (object ):
373
- def test_initial_state (self ):
374
- callback = mock .Mock ()
375
- callback .return_value = True
376
- bidi_rpc = bidi .ResumableBidiRpc (None , callback )
373
+ def test_ctor_defaults (self ):
374
+ start_rpc = mock .Mock ()
375
+ should_recover = mock .Mock ()
376
+ bidi_rpc = bidi .ResumableBidiRpc (start_rpc , should_recover )
377
+
378
+ assert bidi_rpc .is_active is False
379
+ assert bidi_rpc ._finalized is False
380
+ assert bidi_rpc ._start_rpc is start_rpc
381
+ assert bidi_rpc ._should_recover is should_recover
382
+ assert bidi_rpc ._should_terminate is bidi ._never_terminate
383
+ assert bidi_rpc ._initial_request is None
384
+ assert bidi_rpc ._rpc_metadata is None
385
+ assert bidi_rpc ._reopen_throttle is None
386
+
387
+ def test_ctor_explicit (self ):
388
+ start_rpc = mock .Mock ()
389
+ should_recover = mock .Mock ()
390
+ should_terminate = mock .Mock ()
391
+ initial_request = mock .Mock ()
392
+ metadata = {"x-foo" : "bar" }
393
+ bidi_rpc = bidi .ResumableBidiRpc (
394
+ start_rpc ,
395
+ should_recover ,
396
+ should_terminate = should_terminate ,
397
+ initial_request = initial_request ,
398
+ metadata = metadata ,
399
+ throttle_reopen = True ,
400
+ )
377
401
378
402
assert bidi_rpc .is_active is False
403
+ assert bidi_rpc ._finalized is False
404
+ assert bidi_rpc ._should_recover is should_recover
405
+ assert bidi_rpc ._should_terminate is should_terminate
406
+ assert bidi_rpc ._initial_request is initial_request
407
+ assert bidi_rpc ._rpc_metadata == metadata
408
+ assert isinstance (bidi_rpc ._reopen_throttle , bidi ._Throttle )
409
+
410
+ def test_done_callbacks_terminate (self ):
411
+ cancellation = mock .Mock ()
412
+ start_rpc = mock .Mock ()
413
+ should_recover = mock .Mock (spec = ["__call__" ], return_value = True )
414
+ should_terminate = mock .Mock (spec = ["__call__" ], return_value = True )
415
+ bidi_rpc = bidi .ResumableBidiRpc (
416
+ start_rpc , should_recover , should_terminate = should_terminate
417
+ )
418
+ callback = mock .Mock (spec = ["__call__" ])
419
+
420
+ bidi_rpc .add_done_callback (callback )
421
+ bidi_rpc ._on_call_done (cancellation )
422
+
423
+ should_terminate .assert_called_once_with (cancellation )
424
+ should_recover .assert_not_called ()
425
+ callback .assert_called_once_with (cancellation )
426
+ assert not bidi_rpc .is_active
379
427
380
428
def test_done_callbacks_recoverable (self ):
381
429
start_rpc = mock .create_autospec (grpc .StreamStreamMultiCallable , instance = True )
382
- bidi_rpc = bidi .ResumableBidiRpc (start_rpc , lambda _ : True )
430
+ should_recover = mock .Mock (spec = ["__call__" ], return_value = True )
431
+ bidi_rpc = bidi .ResumableBidiRpc (start_rpc , should_recover )
383
432
callback = mock .Mock (spec = ["__call__" ])
384
433
385
434
bidi_rpc .add_done_callback (callback )
386
435
bidi_rpc ._on_call_done (mock .sentinel .future )
387
436
388
437
callback .assert_not_called ()
389
438
start_rpc .assert_called_once ()
439
+ should_recover .assert_called_once_with (mock .sentinel .future )
390
440
assert bidi_rpc .is_active
391
441
392
442
def test_done_callbacks_non_recoverable (self ):
393
- bidi_rpc = bidi .ResumableBidiRpc (None , lambda _ : False )
443
+ start_rpc = mock .create_autospec (grpc .StreamStreamMultiCallable , instance = True )
444
+ should_recover = mock .Mock (spec = ["__call__" ], return_value = False )
445
+ bidi_rpc = bidi .ResumableBidiRpc (start_rpc , should_recover )
394
446
callback = mock .Mock (spec = ["__call__" ])
395
447
396
448
bidi_rpc .add_done_callback (callback )
397
449
bidi_rpc ._on_call_done (mock .sentinel .future )
398
450
399
451
callback .assert_called_once_with (mock .sentinel .future )
452
+ should_recover .assert_called_once_with (mock .sentinel .future )
453
+ assert not bidi_rpc .is_active
454
+
455
+ def test_send_terminate (self ):
456
+ cancellation = ValueError ()
457
+ call_1 = CallStub ([cancellation ], active = False )
458
+ call_2 = CallStub ([])
459
+ start_rpc = mock .create_autospec (
460
+ grpc .StreamStreamMultiCallable , instance = True , side_effect = [call_1 , call_2 ]
461
+ )
462
+ should_recover = mock .Mock (spec = ["__call__" ], return_value = False )
463
+ should_terminate = mock .Mock (spec = ["__call__" ], return_value = True )
464
+ bidi_rpc = bidi .ResumableBidiRpc (start_rpc , should_recover , should_terminate = should_terminate )
465
+
466
+ bidi_rpc .open ()
467
+
468
+ bidi_rpc .send (mock .sentinel .request )
469
+
470
+ assert bidi_rpc .pending_requests == 1
471
+ assert bidi_rpc ._request_queue .get () is None
472
+
473
+ should_recover .assert_not_called ()
474
+ should_terminate .assert_called_once_with (cancellation )
475
+ assert bidi_rpc .call == call_1
476
+ assert bidi_rpc .is_active is False
477
+ assert call_1 .cancelled is True
400
478
401
479
def test_send_recover (self ):
402
480
error = ValueError ()
@@ -441,6 +519,26 @@ def test_send_failure(self):
441
519
assert bidi_rpc .pending_requests == 1
442
520
assert bidi_rpc ._request_queue .get () is None
443
521
522
+ def test_recv_terminate (self ):
523
+ cancellation = ValueError ()
524
+ call = CallStub ([cancellation ])
525
+ start_rpc = mock .create_autospec (
526
+ grpc .StreamStreamMultiCallable , instance = True , return_value = call
527
+ )
528
+ should_recover = mock .Mock (spec = ["__call__" ], return_value = False )
529
+ should_terminate = mock .Mock (spec = ["__call__" ], return_value = True )
530
+ bidi_rpc = bidi .ResumableBidiRpc (start_rpc , should_recover , should_terminate = should_terminate )
531
+
532
+ bidi_rpc .open ()
533
+
534
+ bidi_rpc .recv ()
535
+
536
+ should_recover .assert_not_called ()
537
+ should_terminate .assert_called_once_with (cancellation )
538
+ assert bidi_rpc .call == call
539
+ assert bidi_rpc .is_active is False
540
+ assert call .cancelled is True
541
+
444
542
def test_recv_recover (self ):
445
543
error = ValueError ()
446
544
call_1 = CallStub ([1 , error ])
0 commit comments