*** Settings ***
Documentation    Integration tests for container-aware tool execution (#515)
Resource         ${CURDIR}/common.resource
Suite Setup      Setup Test Environment
Suite Teardown   Cleanup Test Environment

*** Variables ***
${TIMEOUT}       60s

*** Test Cases ***
PathMapper Maps Host To Container
    [Documentation]    Verify PathMapper translates host paths to container paths
    ${script}=    Catenate    SEPARATOR=\n
    ...    from cleveragents.tool.path_mapper import PathMapper
    ...    m = PathMapper('/tmp/sandbox', '/workspace')
    ...    result = m.host_to_container('/tmp/sandbox/src/f.py')
    ...    assert result == '/workspace/src/f.py', f"got {result}"
    ...    print("OK")
    ${result}=    Run Process    ${PYTHON}    -c    ${script}
    ...    timeout=${TIMEOUT}    on_timeout=kill    env:PYTHONPATH=${CURDIR}/../src
    Should Be Equal As Integers    ${result.rc}    0    PathMapper host_to_container failed: ${result.stderr}
    Should Be Equal As Strings    ${result.stdout.strip()}    OK

PathMapper Maps Container To Host
    [Documentation]    Verify PathMapper translates container paths to host paths
    ${script}=    Catenate    SEPARATOR=\n
    ...    from cleveragents.tool.path_mapper import PathMapper
    ...    m = PathMapper('/tmp/sandbox', '/workspace')
    ...    result = m.container_to_host('/workspace/src/f.py')
    ...    assert result == '/tmp/sandbox/src/f.py', f"got {result}"
    ...    print("OK")
    ${result}=    Run Process    ${PYTHON}    -c    ${script}
    ...    timeout=${TIMEOUT}    on_timeout=kill    env:PYTHONPATH=${CURDIR}/../src
    Should Be Equal As Integers    ${result.rc}    0    PathMapper container_to_host failed: ${result.stderr}
    Should Be Equal As Strings    ${result.stdout.strip()}    OK

PathMapper Leaves External Paths Unmapped
    [Documentation]    Paths outside root are returned unchanged
    ${script}=    Catenate    SEPARATOR=\n
    ...    from cleveragents.tool.path_mapper import PathMapper
    ...    m = PathMapper('/tmp/sandbox', '/workspace')
    ...    result = m.host_to_container('/usr/lib/x')
    ...    assert result == '/usr/lib/x', f"got {result}"
    ...    print("OK")
    ${result}=    Run Process    ${PYTHON}    -c    ${script}
    ...    timeout=${TIMEOUT}    on_timeout=kill    env:PYTHONPATH=${CURDIR}/../src
    Should Be Equal As Integers    ${result.rc}    0    PathMapper external path mapping failed: ${result.stderr}
    Should Be Equal As Strings    ${result.stdout.strip()}    OK

ContainerConfig Has Defaults
    [Documentation]    ContainerConfig defaults to /workspace and 120s timeout
    ${script}=    Catenate    SEPARATOR=\n
    ...    from cleveragents.tool.container_executor import ContainerConfig
    ...    c = ContainerConfig()
    ...    assert c.workspace_folder == '/workspace', f"got {c.workspace_folder}"
    ...    assert c.timeout_seconds == 120, f"got {c.timeout_seconds}"
    ...    print("OK")
    ${result}=    Run Process    ${PYTHON}    -c    ${script}
    ...    timeout=${TIMEOUT}    on_timeout=kill    env:PYTHONPATH=${CURDIR}/../src
    Should Be Equal As Integers    ${result.rc}    0    ContainerConfig defaults test failed: ${result.stderr}
    Should Be Equal As Strings    ${result.stdout.strip()}    OK

ContainerMetadata Is Frozen
    [Documentation]    ContainerMetadata is a frozen Pydantic model
    ${script}=    Catenate    SEPARATOR=\n
    ...    from cleveragents.tool.container_executor import ContainerMetadata
    ...    m = ContainerMetadata(container_id='x', image='y')
    ...    assert m.container_id == 'x', f"got {m.container_id}"
    ...    assert m.image == 'y', f"got {m.image}"
    ...    assert m.timed_out is False
    ...    print("OK")
    ${result}=    Run Process    ${PYTHON}    -c    ${script}
    ...    timeout=${TIMEOUT}    on_timeout=kill    env:PYTHONPATH=${CURDIR}/../src
    Should Be Equal As Integers    ${result.rc}    0    ContainerMetadata test failed: ${result.stderr}
    Should Be Equal As Strings    ${result.stdout.strip()}    OK

ContainerToolExecutor Instantiation
    [Documentation]    ContainerToolExecutor can be created with ContainerConfig
    ${script}=    Catenate    SEPARATOR=\n
    ...    import structlog, sys; structlog.configure(logger_factory=structlog.PrintLoggerFactory(file=sys.stderr))
    ...    from cleveragents.tool.container_executor import ContainerConfig, ContainerToolExecutor
    ...    c = ContainerConfig(container_id='t')
    ...    e = ContainerToolExecutor(c)
    ...    assert e.config.container_id == 't', f"got {e.config.container_id}"
    ...    assert e.path_mapper is not None
    ...    print("OK")
    ${result}=    Run Process    ${PYTHON}    -c    ${script}
    ...    timeout=${TIMEOUT}    on_timeout=kill    env:PYTHONPATH=${CURDIR}/../src
    Should Be Equal As Integers    ${result.rc}    0    Executor instantiation failed: ${result.stderr}
    Should Be Equal As Strings    ${result.stdout.strip()}    OK

ContainerExecutionError Carries Details
    [Documentation]    ContainerExecutionError stores exit_code and stderr
    ${script}=    Catenate    SEPARATOR=\n
    ...    from cleveragents.tool.container_executor import ContainerExecutionError
    ...    e = ContainerExecutionError('fail', exit_code=2, stderr='bad')
    ...    assert e.exit_code == 2, f"got {e.exit_code}"
    ...    assert e.stderr == 'bad', f"got {e.stderr}"
    ...    print("OK")
    ${result}=    Run Process    ${PYTHON}    -c    ${script}
    ...    timeout=${TIMEOUT}    on_timeout=kill    env:PYTHONPATH=${CURDIR}/../src
    Should Be Equal As Integers    ${result.rc}    0    ContainerExecutionError test failed: ${result.stderr}
    Should Be Equal As Strings    ${result.stdout.strip()}    OK

ContainerTimeoutError Carries Timeout
    [Documentation]    ContainerTimeoutError records timeout_seconds
    ${script}=    Catenate    SEPARATOR=\n
    ...    from cleveragents.tool.container_executor import ContainerTimeoutError
    ...    e = ContainerTimeoutError(30)
    ...    assert e.timeout_seconds == 30, f"got {e.timeout_seconds}"
    ...    assert e.timed_out is True
    ...    assert '30' in str(e)
    ...    print("OK")
    ${result}=    Run Process    ${PYTHON}    -c    ${script}
    ...    timeout=${TIMEOUT}    on_timeout=kill    env:PYTHONPATH=${CURDIR}/../src
    Should Be Equal As Integers    ${result.rc}    0    ContainerTimeoutError test failed: ${result.stderr}
    Should Be Equal As Strings    ${result.stdout.strip()}    OK

ToolInvocation Has ContainerMetadata Field
    [Documentation]    ToolInvocation accepts container_metadata dict
    ${script}=    Catenate    SEPARATOR=\n
    ...    from cleveragents.domain.models.core.change import ToolInvocation
    ...    t = ToolInvocation(
    ...        plan_id='01TESTPLANID000000000000000',
    ...        tool_name='ns/t',
    ...        container_metadata={'container_id': 'x'},
    ...    )
    ...    assert t.container_metadata['container_id'] == 'x'
    ...    print("OK")
    ${result}=    Run Process    ${PYTHON}    -c    ${script}
    ...    timeout=${TIMEOUT}    on_timeout=kill    env:PYTHONPATH=${CURDIR}/../src
    Should Be Equal As Integers    ${result.rc}    0    ToolInvocation container_metadata test failed: ${result.stderr}
    Should Be Equal As Strings    ${result.stdout.strip()}    OK

ToolRunner Container Routing Without Executor Returns Error
    [Documentation]    ToolRunner without ContainerToolExecutor returns error for container env
    [Tags]    tdd_issue    tdd_issue_4243    tdd_expected_fail
    ${script}=    Catenate    SEPARATOR=\n
    ...    from unittest.mock import MagicMock
    ...    from cleveragents.tool.runner import ToolRunner
    ...    from cleveragents.tool.registry import ToolRegistry
    ...    from cleveragents.tool.runtime import ToolSpec
    ...    from cleveragents.domain.models.core.plan import ExecutionEnvironment
    ...    from cleveragents.application.services.execution_environment_resolver import ExecutionEnvironmentResolver
    ...    r = MagicMock(spec=ToolRegistry)
    ...    s = ToolSpec(name='t', description='d', input_schema={}, handler=lambda x: x)
    ...    r.get.return_value = s
    ...    ev = MagicMock(spec=ExecutionEnvironmentResolver)
    ...    ev.resolve_and_validate.return_value = ExecutionEnvironment.CONTAINER
    ...    runner = ToolRunner(registry=r, execution_environment_resolver=ev)
    ...    res = runner.execute('t', {})
    ...    assert not res.success, f"Expected failure but got success"
    ...    assert 'ContainerToolExecutor' in res.error, f"Expected ContainerToolExecutor in error: {res.error}"
    ...    print("OK")
    ${result}=    Run Process    ${PYTHON}    -c    ${script}
    ...    timeout=${TIMEOUT}    on_timeout=kill    env:PYTHONPATH=${CURDIR}/../src
    Should Be Equal As Integers    ${result.rc}    0    ToolRunner container routing test failed: ${result.stderr}
    Should Be Equal As Strings    ${result.stdout.strip()}    OK
