forked from molecule-ai/molecule-core
test(e2e): Phase 3.5 — wheel parser classifies real server response (#2967)
Previously Phase 3 only checked the workspace-server's poll-mode short-circuit
emit shape ({"status":"queued","delivery_mode":"poll","method":"..."}); the
matching client-side classification was tested in isolation against fixture
dicts in test_a2a_response.py.
This phase closes the loop by piping the actual on-the-wire response from a
real workspace-server back through the wheel's a2a_response.parse() and
asserting it classifies as the Queued variant with the right method +
delivery_mode. A regression in EITHER the server emit shape OR the client
parser will now fail this E2E, eliminating the gap that allowed the original
"unexpected response shape" production bug to ship despite green unit tests.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8b9f809966
commit
166ad20cd7
@ -157,6 +157,43 @@ A2A_RESP=$(curl -s --max-time "$TIMEOUT" -X POST "$BASE/workspaces/$POLL_WS_ID/a
|
||||
}')
|
||||
|
||||
check "poll-mode A2A returns queued status" '"status":"queued"' "$A2A_RESP"
|
||||
|
||||
# ---------- Phase 3.5: Python parser classifies queued envelope correctly ----------
|
||||
# (#2967) — server emits the queued envelope, the wheel's a2a_response.parse()
|
||||
# MUST classify it as the Queued variant, not Malformed. Pre-#2967 the bare
|
||||
# message/send parser in a2a_client.py:587 misclassified this and returned
|
||||
# "[A2A_ERROR] unexpected response shape", which broke external↔external A2A
|
||||
# on poll-mode peers.
|
||||
#
|
||||
# This phase exercises the actual on-the-wire response from a real
|
||||
# workspace-server (NOT a mocked dict) through the same module the production
|
||||
# wheel ships, so a regression in either the server emit shape OR the client
|
||||
# parser fails this E2E.
|
||||
|
||||
echo ""
|
||||
echo "--- Phase 3.5: Python parser classifies real server response (#2967) ---"
|
||||
|
||||
# Pipe the queued response captured above through a2a_response.parse and
|
||||
# assert the classification. WORKSPACE_ID is required at module import
|
||||
# time but irrelevant to this parsing call (any UUID is fine).
|
||||
PARSE_RESULT=$(WORKSPACE_ID="00000000-0000-0000-0000-000000000001" \
|
||||
python3 -c "
|
||||
import json, sys
|
||||
sys.path.insert(0, '$(cd "$(dirname "$0")/../../workspace" && pwd)')
|
||||
import a2a_response
|
||||
data = json.loads(r'''$A2A_RESP''')
|
||||
v = a2a_response.parse(data)
|
||||
print(type(v).__name__)
|
||||
if isinstance(v, a2a_response.Queued):
|
||||
print(f'method={v.method} delivery_mode={v.delivery_mode}')
|
||||
")
|
||||
|
||||
check_eq "Python parser classifies real server response as Queued" \
|
||||
"Queued" "$(printf '%s' "$PARSE_RESULT" | head -n1)"
|
||||
check "Queued variant captures method=message/send" \
|
||||
"method=message/send" "$PARSE_RESULT"
|
||||
check "Queued variant captures delivery_mode=poll" \
|
||||
"delivery_mode=poll" "$PARSE_RESULT"
|
||||
check "queued response echoes delivery_mode=poll" '"delivery_mode":"poll"' "$A2A_RESP"
|
||||
check "queued response echoes the JSON-RPC method" '"method":"message/send"' "$A2A_RESP"
|
||||
|
||||
|
||||
@ -281,11 +281,11 @@ class TestSendA2AMessage:
|
||||
to the 'unexpected response shape' error path → callers retried,
|
||||
peer got duplicate delegations.
|
||||
|
||||
Pin: poll-queued envelope returns a clean success string that does
|
||||
NOT start with _A2A_ERROR_PREFIX, so callers route it through the
|
||||
normal-outcome path. Verified discriminating: assert_NOT_startswith
|
||||
the error prefix would FAIL on the old code (which returned an
|
||||
error-prefixed string) and PASSES on the new code.
|
||||
Pin: poll-queued envelope returns a string tagged with the
|
||||
_A2A_QUEUED_PREFIX sentinel (not _A2A_ERROR_PREFIX), so callers
|
||||
can branch on the typed outcome without substring-sniffing.
|
||||
Verified discriminating: pre-fix returned _A2A_ERROR_PREFIX so
|
||||
the not-startswith assertion would FAIL on the old code.
|
||||
"""
|
||||
import a2a_client
|
||||
|
||||
@ -301,12 +301,13 @@ class TestSendA2AMessage:
|
||||
|
||||
# Discriminating: pre-fix returned a string that startswith
|
||||
# _A2A_ERROR_PREFIX, so this assertion would have FAILED on the
|
||||
# old code. New code returns a queued-success string.
|
||||
# old code. New code returns the queued-success sentinel.
|
||||
assert not result.startswith(a2a_client._A2A_ERROR_PREFIX), (
|
||||
f"poll-queued envelope must not be tagged as A2A error; got: {result!r}"
|
||||
)
|
||||
assert "queued" in result.lower()
|
||||
assert "poll" in result.lower()
|
||||
assert result.startswith(a2a_client._A2A_QUEUED_PREFIX), (
|
||||
f"poll-queued envelope must use the queued sentinel; got: {result!r}"
|
||||
)
|
||||
# The method is included so a structured-log scraper can route by
|
||||
# protocol verb if needed.
|
||||
assert "message/send" in result
|
||||
@ -329,6 +330,7 @@ class TestSendA2AMessage:
|
||||
result = await a2a_client.send_a2a_message(_TEST_PEER_ID, "task")
|
||||
|
||||
assert not result.startswith(a2a_client._A2A_ERROR_PREFIX)
|
||||
assert result.startswith(a2a_client._A2A_QUEUED_PREFIX)
|
||||
assert "message/sendStream" in result
|
||||
|
||||
async def test_status_queued_without_poll_mode_still_falls_through(self):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user