forked from goodboy/tractor
1
0
Fork 0

Ensure ctx error-state matches the MTE scenario

Namely checking that `Context._remote_error` is set to the raised MTE
in the invalid started and return value cases since prior to the recent
underlying changes to the `Context.result()` impl, it would not match.

Further,
- do asserts for non-MTE raising cases in both the parent and child.
- add todos for testing ctx-outcomes for per-side-validation policies
  i anticipate supporting and implied msg-dialog race cases therein.
runtime_to_msgspec
Tyler Goodlet 2024-05-28 19:46:42 -04:00
parent 6a4ee461f5
commit 4fa71cc01c
1 changed files with 71 additions and 18 deletions

View File

@ -148,13 +148,45 @@ async def child(
# propagate to parent? # propagate to parent?
if raise_on_started_mte: if raise_on_started_mte:
raise raise
else:
if expect_started_mte: # no-send-side-error fallthrough
if (
validate_pld_spec
and
expect_started_mte
):
raise RuntimeError( raise RuntimeError(
'Child-ctx-task SHOULD HAVE raised an MTE for\n\n' 'Child-ctx-task SHOULD HAVE raised an MTE for\n\n'
f'{started_value!r}\n' f'{started_value!r}\n'
) )
assert (
not expect_started_mte
or
not validate_pld_spec
)
# if wait_for_parent_to_cancel:
# ...
#
# ^-TODO-^ logic for diff validation policies on each side:
#
# -[ ] ensure that if we don't validate on the send
# side, that we are eventually error-cancelled by our
# parent due to the bad `Started` payload!
# -[ ] the boxed error should be srced from the parent's
# runtime NOT ours!
# -[ ] we should still error on bad `return_value`s
# despite the parent not yet error-cancelling us?
# |_ how do we want the parent side to look in that
# case?
# -[ ] maybe the equiv of "during handling of the
# above error another occurred" for the case where
# the parent sends a MTE to this child and while
# waiting for the child to terminate it gets back
# the MTE for this case?
#
# XXX should always fail on recv side since we can't # XXX should always fail on recv side since we can't
# really do much else beside terminate and relay the # really do much else beside terminate and relay the
# msg-type-error from this RPC task ;) # msg-type-error from this RPC task ;)
@ -247,13 +279,17 @@ def test_basic_payload_spec(
msg_type_str: str = '' msg_type_str: str = ''
bad_value_str: str = '' bad_value_str: str = ''
async with ( maybe_mte: MsgTypeError|None = None
maybe_expect_raises( should_raise: Exception|None = (
raises=MsgTypeError if ( MsgTypeError if (
invalid_return invalid_return
or or
invalid_started invalid_started
) else None, ) else None
)
async with (
maybe_expect_raises(
raises=should_raise,
ensure_in_message=[ ensure_in_message=[
f"invalid `{msg_type_str}` payload", f"invalid `{msg_type_str}` payload",
f"value: `{bad_value_str}` does not match type-spec: `{msg_type_str}.pld: PldMsg|NoneType`", f"value: `{bad_value_str}` does not match type-spec: `{msg_type_str}.pld: PldMsg|NoneType`",
@ -274,18 +310,35 @@ def test_basic_payload_spec(
assert first.field == 'yo' assert first.field == 'yo'
try: try:
assert (await ctx.result()) is None res: None|PldMsg = await ctx.result(hide_tb=False)
assert res is None
except MsgTypeError as mte: except MsgTypeError as mte:
maybe_mte = mte
if not invalid_return: if not invalid_return:
raise raise
else: # expected this invalid `Return.pld` # expected this invalid `Return.pld` so audit
# the error state + meta-data
assert mte.expected_msg_type is Return
assert mte.cid == ctx.cid assert mte.cid == ctx.cid
# verify expected remote mte deats # verify expected remote mte deats
await tractor.pause() try:
assert ctx._remote_error is mte assert ctx._local_error is None
assert mte.expected_msg_type is Return assert (
mte is
ctx._remote_error is
ctx.maybe_error is
ctx.outcome
)
except:
# XXX should never get here..
await tractor.pause(shield=True)
raise
if should_raise is None:
assert maybe_mte is None
await p.cancel_actor() await p.cancel_actor()