Tweak inter-peer tests for new/refined semantics
Buncha subtle details changed mostly to do with when `Context.cancel()` gets called on "real" remote errors vs. (peer requested) cancellation and then local side handling of `ContextCancelled`. Specific changes to make tests pass: - due to raciness with `sleeper_ctx.result()` raising the ctxc locally vs. the child-peers receiving similar ctxcs themselves (and then erroring and propagating back to the root parent), we might not see `._remote_error` set during the sub-ctx loops (except for the sleeper itself obvi). - do not expect `.cancel_called`/`.cancel_caught` to be set on any sub-ctx since currently `Context.cancel()` is only called non-shielded and thus is not in invoked when `._scope.cancel()` is called as part of each root-side ctx ref/block handling the inter-peer ctxc. - do not expect `Context._scope.cancelled_caught` to be set in most cases (even the sleeper) TODO Outstanding adjustments not fixed yet: -[ ] `_scope.cancelled_caught` checks outside the `.open_context()` blocks.shielded_ctx_cancel
							parent
							
								
									7c22f76274
								
							
						
					
					
						commit
						9e3f41a5b1
					
				|  | @ -220,11 +220,12 @@ async def stream_from_peer( | |||
|             # - what about IPC-transport specific errors, should | ||||
|             #   they bubble from the async for and trigger | ||||
|             #   other special cases? | ||||
|             # | ||||
|             # NOTE: current ctl flow: | ||||
|             # - stream raises `trio.EndOfChannel` and | ||||
|             #   exits the loop | ||||
|             # - `.open_context()` will raise the ctxcanc | ||||
|             #   received from the sleeper. | ||||
|             # - `.open_context()` will raise the ctxc received | ||||
|             #   from the sleeper. | ||||
|             async for msg in stream: | ||||
|                 assert msg is not None | ||||
|                 print(msg) | ||||
|  | @ -383,11 +384,11 @@ def test_peer_canceller( | |||
|                     ) as (canceller_ctx, sent), | ||||
| 
 | ||||
|                 ): | ||||
|                     ctxs: list[Context] = [ | ||||
|                         sleeper_ctx, | ||||
|                         caller_ctx, | ||||
|                         canceller_ctx, | ||||
|                     ] | ||||
|                     ctxs: dict[str, Context] = { | ||||
|                         'sleeper': sleeper_ctx, | ||||
|                         'caller': caller_ctx, | ||||
|                         'canceller': canceller_ctx, | ||||
|                     } | ||||
| 
 | ||||
|                     try: | ||||
|                         print('PRE CONTEXT RESULT') | ||||
|  | @ -505,14 +506,17 @@ def test_peer_canceller( | |||
|                     # NOTE: this root actor task should have | ||||
|                     # called `Context.cancel()` on the | ||||
|                     # `.__aexit__()` to every opened ctx. | ||||
|                     for ctx in ctxs: | ||||
|                         assert ctx.cancel_called | ||||
|                     for name, ctx in ctxs.items(): | ||||
| 
 | ||||
|                         # this root actor task should have | ||||
|                         # cancelled all opened contexts except the | ||||
|                         # sleeper which is obvi by the "canceller" | ||||
|                         # peer. | ||||
|                         re = ctx._remote_error | ||||
|                         le = ctx._local_error | ||||
| 
 | ||||
|                         assert ctx.cancel_called | ||||
| 
 | ||||
|                         if ( | ||||
|                             ctx is sleeper_ctx | ||||
|                             or ctx is caller_ctx | ||||
|  | @ -566,32 +570,43 @@ def test_peer_canceller( | |||
| 
 | ||||
|                     # the sleeper's remote error is the error bubbled | ||||
|                     # out of the context-stack above! | ||||
|                     re = sleeper_ctx.outcome | ||||
|                     final_err = sleeper_ctx.outcome | ||||
|                     assert ( | ||||
|                         re is loc_err | ||||
|                         final_err is loc_err | ||||
|                         is sleeper_ctx.maybe_error | ||||
|                         is sleeper_ctx._remote_error | ||||
|                     ) | ||||
| 
 | ||||
|                     for ctx in ctxs: | ||||
|                     for name, ctx in ctxs.items(): | ||||
| 
 | ||||
|                         re: BaseException|None = ctx._remote_error | ||||
|                         re: BaseException|None = ctx.outcome | ||||
|                         assert ( | ||||
|                             re and | ||||
|                             ( | ||||
|                                 re is ctx.maybe_error | ||||
|                                 is ctx._remote_error | ||||
|                             ) | ||||
|                         ) | ||||
|                         le: trio.MultiError = ctx._local_error | ||||
|                         le: BaseException|None = ctx._local_error | ||||
|                         err = ctx.maybe_error | ||||
|                         out = ctx.outcome | ||||
| 
 | ||||
|                         # every ctx should error! | ||||
|                         assert out is err | ||||
| 
 | ||||
|                         # the recorded local erro should always be | ||||
|                         # the same as the one raised by the | ||||
|                         # `sleeper_ctx.result()` call | ||||
|                         assert ( | ||||
|                             le | ||||
|                             and ctx._local_error | ||||
|                             and | ||||
|                             le is loc_err | ||||
|                         ) | ||||
| 
 | ||||
|                         # root doesn't cancel sleeper since it's | ||||
|                         # cancelled by its peer. | ||||
|                         if ctx is sleeper_ctx: | ||||
|                             assert re | ||||
|                             assert ( | ||||
|                                 ctx._remote_error | ||||
|                                 is ctx.maybe_error | ||||
|                                 is ctx.outcome | ||||
|                                 is ctx._local_error | ||||
|                             ) | ||||
| 
 | ||||
|                             assert not ctx.cancel_called | ||||
|                             assert not ctx.cancel_acked | ||||
| 
 | ||||
|  | @ -601,21 +616,38 @@ def test_peer_canceller( | |||
|                             # `ContextCancelled` for it and thus | ||||
|                             # the logic inside `.cancelled_caught` | ||||
|                             # should trigger! | ||||
|                             assert ctx._scope.cancelled_caught | ||||
|                             assert not ctx._scope.cancelled_caught | ||||
| 
 | ||||
|                         elif ctx is caller_ctx: | ||||
|                         elif ctx in ( | ||||
|                             caller_ctx, | ||||
|                             canceller_ctx, | ||||
|                         ): | ||||
| 
 | ||||
|                             assert not ctx._remote_error | ||||
| 
 | ||||
|                             # the `canceller_ctx` shouldn't | ||||
|                             # have called `ctx.cancel()` either! | ||||
|                             # | ||||
|                             # since its context was remotely | ||||
|                             # cancelled, we never needed to | ||||
|                             # call `Context.cancel()` bc it was | ||||
|                             # done by the peer and also we never  | ||||
|                             assert ctx.cancel_called | ||||
|                             # cancelled, we never needed to call | ||||
|                             # `Context.cancel()` bc the far end | ||||
|                             # task already done by the peer and | ||||
|                             # also we never  | ||||
|                             assert not ctx.cancel_called | ||||
| 
 | ||||
|                             # TODO: figure out the details of this..? | ||||
|                             # if you look the `._local_error` here | ||||
|                             # is a multi of ctxc + 2 Cancelleds? | ||||
|                             # assert not ctx.cancelled_caught | ||||
| 
 | ||||
|                         elif ctx is canceller_ctx: | ||||
|                             assert ( | ||||
|                                 not ctx.cancel_called | ||||
|                                 and not ctx.cancel_acked | ||||
|                             ) | ||||
|                             assert not ctx._scope.cancelled_caught | ||||
| 
 | ||||
|                         # elif ctx is canceller_ctx: | ||||
|                         #     assert not ctx._remote_error | ||||
| 
 | ||||
|                             # XXX NOTE XXX: ONLY the canceller | ||||
|                             # will get a self-cancelled outcome | ||||
|  | @ -626,11 +658,6 @@ def test_peer_canceller( | |||
|                             # .cancel() whenever an interpeer | ||||
|                             # cancel takes place since each | ||||
|                             # reception of a ctxc | ||||
|                             assert ( | ||||
|                                 ctx.cancel_called | ||||
|                                 and ctx.cancel_acked | ||||
|                             ) | ||||
|                             assert not ctx._scope.cancelled_caught | ||||
| 
 | ||||
|                         else: | ||||
|                             pytest.fail( | ||||
|  | @ -663,7 +690,7 @@ def test_peer_canceller( | |||
|                 # `.open_context()` block has exited and should be | ||||
|                 # set in both outcomes including the case where | ||||
|                 # ctx-cancel handling itself errors. | ||||
|                 assert sleeper_ctx._scope.cancelled_caught | ||||
|                 assert not sleeper_ctx._scope.cancelled_caught | ||||
|                 assert _loc_err is sleeper_ctx._local_error | ||||
|                 assert ( | ||||
|                     sleeper_ctx.outcome | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue