a2aproject / a2aproject/a2a-tck
test_tasks_cancel_valid: race condition causes false failures on synchronous agents
- Vorherrschende Sprache
- Python
- Sterne
- 50
- Forks
- 40
- Ø Merge
- 7 T. 1 Std.
- Gemergte PRs (30 T.)
- 1
Beschreibung
## Problem
`tests/mandatory/protocol/test_tasks_cancel_method.py::test_tasks_cancel_valid` has a race condition that causes false failures when the System Under Test (SUT) processes tasks synchronously.
## Root Cause
The test fixture creates a task, then immediately tries to cancel it:
```python
@pytest.fixture
def created_task_id(sut_client):
resp = transport_send_message(sut_client, params)
task_id = extract_task_id_from_response(resp)
return task_id # Task may already be COMPLETED!
def test_tasks_cancel_valid(sut_client, created_task_id):
resp = transport_cancel_task(sut_client, created_task_id)
assert is_json_rpc_success_response(resp) # FAILS if task already completed
```
When a SUT agent processes tasks synchronously (common in simple/test agents), the task transitions from `TASK_STATE_SUBMITTED → TASK_STATE_WORKING → TASK_STATE_COMPLETED` before the cancel request arrives. The agent then correctly returns:
```json
{"error": {"code": -32002, "message": "Task cannot be canceled - current state: 3"}}
```
## Why This Is Correct Behavior
Per A2A v1.0 spec §3.3.2:
> `TaskNotCancelableError (-32002)`: An attempt was made to cancel a task that is not in a cancelable state (e.g., it has already reached a terminal state like completed, failed, or canceled).
The agent returning `-32002` on a completed task is **correct behavior**. The TCK is marking a compliant implementation as non-compliant.
## Reproduction
1. Run the TCK against the built-in `python-sut/tck_core_agent` using the `a2a-sdk==1.0.0a0`
2. The agent completes tasks synchronously in its executor
3. `test_tasks_cancel_valid` FAILS with the correct -32002 error
```
FAILED tests/mandatory/protocol/test_tasks_cancel_method.py::test_tasks_cancel_valid
AssertionError: Task cancellation failed: {'error': {'code': -32002, 'message': 'Task cannot be canceled - current state: 3'}}
```
## Also affected
`tests/mandatory/protocol/test_a2a_v030_new_methods.py::TestMethodMappingCompliance::test_core_method_mapping_compliance` has the same issue — it creates a task and immediately cancels it.
## Fix
The test must cancel a task while it's in `TASK_STATE_WORKING` state. The SUT Requirements already document a mechanism for this:
> Tasks with message IDs starting with `"test-resubscribe-message-id"` must run for ≥ `2 × TCK_STREAMING_TIMEOUT` seconds
**Proposed fix:**
```python
@pytest.fixture
def created_task_id(sut_client):
# Use the long-running task ID prefix per SUT requirements
params = {
"message": {
"messageId": "test-resubscribe-message-id-cancel-test-" + str(uuid.uuid4()),
"role": "ROLE_USER",
"parts": [{"text": "Task for cancel test"}],
}
}
resp = transport_send_message(sut_client, params)
task_id = extract_task_id_from_response(resp)
# Wait for WORKING state before attempting cancel
max_wait = 5
start = time.time()
while time.time() - start < max_wait:
get_resp = transport_get_task(sut_client, task_id)
state = get_resp.get("result", {}).get("status", {}).get("state", "")
if state == "TASK_STATE_WORKING":
break
time.sleep(0.1)
return task_id
```
## Spec Reference
- A2A v1.0 §3.1.5. Cancel Task
- A2A v1.0 §3.3.2 Error Handling — `TaskNotCancelableError (-32002)`
- TCK docs/SUT_REQUIREMENTS.md — long-running task pattern
Beitragsleitfaden
Bewertung
Dieses Issue wurde noch nicht bewertet.