Files
cleveragents-core/robot/security_async.robot
brent.edwards 3eecb79003
CI / lint (pull_request) Successful in 16s
CI / quality (pull_request) Successful in 46s
CI / typecheck (pull_request) Successful in 56s
CI / security (pull_request) Successful in 56s
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 29s
CI / e2e_tests (pull_request) Successful in 2m7s
CI / unit_tests (pull_request) Successful in 3m8s
CI / docker (pull_request) Successful in 9s
CI / integration_tests (pull_request) Successful in 3m57s
CI / coverage (pull_request) Successful in 7m48s
CI / benchmark-regression (pull_request) Successful in 40m48s
test(plan): TDD failing tests for checkpoint real rollback (bug #822)
TDD expected-fail tests proving bug #822 exists:
CheckpointService.rollback_to_checkpoint() returns a successful
RollbackResult but does not execute git reset --hard. Files modified
after the checkpoint remain unchanged after rollback.

Also fixes Robot Framework timeout robustness across the entire test
suite: all Run Process calls now use on_timeout=kill (prevents
SIGTERM-induced -15 exit codes under CI load) and timeouts increased
to 120s (prevents premature kills during heavy parallel execution).

ISSUES CLOSED: #839
2026-03-16 01:45:50 +00:00

136 lines
6.2 KiB
Plaintext

*** Settings ***
Documentation Integration smoke tests for async resource cleanup (#321).
... Validates that AsyncResourceTracker, enhanced bridge cleanup,
... A2aEventQueue.close(), and StateManager.close() work end-to-end
... by executing small Python driver scripts in a subprocess.
Library OperatingSystem
Library Process
Library String
Resource ${CURDIR}/common.resource
Test Setup Setup Async Cleanup Test Environment
Test Teardown Cleanup Async Cleanup Test Environment
*** Variables ***
${PYTHON} python
${WORKSPACE_ROOT} ${CURDIR}/..
${TEST_FILE} ${EMPTY}
${TEST_OUTPUT} ${EMPTY}
${TIMEOUT} 30s
*** Test Cases ***
Test AsyncResourceTracker Register And Close
[Documentation] Register a resource and close it via close_all
${script} = Catenate SEPARATOR=\n
... import sys, asyncio
... sys.path.insert(0, '${WORKSPACE_ROOT}/src')
... from cleveragents.core.async_cleanup import AsyncResourceTracker
...
... class FakeResource:
... ${SPACE}${SPACE}${SPACE}${SPACE}def __init__(self): self.closed = False
... ${SPACE}${SPACE}${SPACE}${SPACE}async def close(self): self.closed = True
...
... async def main():
... ${SPACE}${SPACE}${SPACE}${SPACE}tracker = AsyncResourceTracker()
... ${SPACE}${SPACE}${SPACE}${SPACE}res = FakeResource()
... ${SPACE}${SPACE}${SPACE}${SPACE}tracker.register("test-res", res)
... ${SPACE}${SPACE}${SPACE}${SPACE}assert tracker.open_count == 1
... ${SPACE}${SPACE}${SPACE}${SPACE}await tracker.close_all()
... ${SPACE}${SPACE}${SPACE}${SPACE}assert res.closed
... ${SPACE}${SPACE}${SPACE}${SPACE}assert tracker.open_count == 0
... ${SPACE}${SPACE}${SPACE}${SPACE}print("PASS: register and close", flush=True)
...
... asyncio.run(main())
Create File ${TEST_FILE} ${script}
${result} = Run Process ${PYTHON} ${TEST_FILE}
... stdout=${TEST_OUTPUT} stderr=STDOUT timeout=${TIMEOUT} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
${output} = Get File ${TEST_OUTPUT}
Should Contain ${output} PASS: register and close
Test AsyncResourceTracker Timeout Warning
[Documentation] Verify forced-termination warning for slow resource
${script} = Catenate SEPARATOR=\n
... import sys, asyncio, logging
... sys.path.insert(0, '${WORKSPACE_ROOT}/src')
... from cleveragents.core.async_cleanup import AsyncResourceTracker
...
... handler = logging.StreamHandler(sys.stdout)
... handler.setLevel(logging.WARNING)
... logging.getLogger("cleveragents.core.async_cleanup").addHandler(handler)
...
... class SlowResource:
... ${SPACE}${SPACE}${SPACE}${SPACE}async def close(self): await asyncio.sleep(10)
...
... async def main():
... ${SPACE}${SPACE}${SPACE}${SPACE}tracker = AsyncResourceTracker()
... ${SPACE}${SPACE}${SPACE}${SPACE}tracker.register("slow", SlowResource())
... ${SPACE}${SPACE}${SPACE}${SPACE}await tracker.close_all(timeout=0.05)
... ${SPACE}${SPACE}${SPACE}${SPACE}assert len(tracker.timed_out_resources) == 1
... ${SPACE}${SPACE}${SPACE}${SPACE}print("PASS: timeout warning", flush=True)
...
... asyncio.run(main())
Create File ${TEST_FILE} ${script}
${result} = Run Process ${PYTHON} ${TEST_FILE}
... stdout=${TEST_OUTPUT} stderr=STDOUT timeout=${TIMEOUT} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
${output} = Get File ${TEST_OUTPUT}
Should Contain ${output} PASS: timeout warning
Test A2aEventQueue Close
[Documentation] Verify A2aEventQueue.close() removes subscriptions
${script} = Catenate SEPARATOR=\n
... import sys
... sys.path.insert(0, '${WORKSPACE_ROOT}/src')
... from cleveragents.a2a.events import A2aEventQueue
...
... q = A2aEventQueue()
... q.subscribe_local(lambda e: None)
... q.subscribe_local(lambda e: None)
... assert len(q._subscriptions) == 2
... q.close()
... assert len(q._subscriptions) == 0
... print("PASS: event queue close", flush=True)
Create File ${TEST_FILE} ${script}
${result} = Run Process ${PYTHON} ${TEST_FILE}
... stdout=${TEST_OUTPUT} stderr=STDOUT timeout=${TIMEOUT} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
${output} = Get File ${TEST_OUTPUT}
Should Contain ${output} PASS: event queue close
Test StateManager Close
[Documentation] Verify StateManager.close() marks manager as closed
${script} = Catenate SEPARATOR=\n
... import sys, tempfile
... sys.path.insert(0, '${WORKSPACE_ROOT}/src')
... from pathlib import Path
... from cleveragents.langgraph.state import StateManager, GraphState
...
... d = tempfile.mkdtemp()
... mgr = StateManager(initial_state=GraphState(), checkpoint_dir=Path(d))
... assert not mgr.is_closed
... mgr.close()
... assert mgr.is_closed
... print("PASS: state manager close", flush=True)
Create File ${TEST_FILE} ${script}
${result} = Run Process ${PYTHON} ${TEST_FILE}
... stdout=${TEST_OUTPUT} stderr=STDOUT timeout=${TIMEOUT} on_timeout=kill
Should Be Equal As Integers ${result.rc} 0
${output} = Get File ${TEST_OUTPUT}
Should Contain ${output} PASS: state manager close
*** Keywords ***
Setup Async Cleanup Test Environment
[Documentation] Create temp dir for test scripts
${temp_dir} = Evaluate tempfile.mkdtemp() modules=tempfile
Set Test Variable ${TEMP_DIR} ${temp_dir}
Set Test Variable ${TEST_FILE} ${temp_dir}/async_cleanup_test.py
Set Test Variable ${TEST_OUTPUT} ${temp_dir}/async_cleanup_output.txt
Cleanup Async Cleanup Test Environment
[Documentation] Remove temp dir
Run Keyword And Ignore Error Remove File ${TEST_FILE}
Run Keyword And Ignore Error Remove File ${TEST_OUTPUT}
Run Keyword And Ignore Error Remove Directory ${TEMP_DIR} recursive=True