4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
127 lines
3.9 KiB
Python
127 lines
3.9 KiB
Python
"""Tests for TracerToolsMixin."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from integrations.tracer.tracer_tools import TracerToolsMixin
|
|
|
|
|
|
class FakeTracerClient(TracerToolsMixin):
|
|
"""Fake subclass that stubs _get()."""
|
|
|
|
def __init__(self) -> None:
|
|
"""Initialize with dummy values, avoiding side effects from base class."""
|
|
with (
|
|
patch(
|
|
"integrations.tracer.tracer_client_base.extract_org_slug_from_jwt",
|
|
return_value="test-slug",
|
|
),
|
|
patch("httpx.Client"),
|
|
):
|
|
super().__init__(
|
|
base_url="https://api.tracer.cloud", org_id="test-org", jwt_token="dummy-jwt"
|
|
)
|
|
self._get_response: dict[str, Any] = {}
|
|
|
|
def _get(self, _endpoint: str, _params: Any = None) -> dict[str, Any]:
|
|
"""Stub for the GET request."""
|
|
return self._get_response
|
|
|
|
|
|
def test_get_run_tasks_all_success() -> None:
|
|
"""Test get_run_tasks when all tasks are successful."""
|
|
client = FakeTracerClient()
|
|
client._get_response = {
|
|
"success": True,
|
|
"data": [
|
|
{"tool_name": "ls", "exit_code": "0", "runtime_ms": 100},
|
|
{"tool_name": "pwd", "exit_code": None, "runtime_ms": 50},
|
|
{"tool_name": "whoami", "exit_code": "", "runtime_ms": 75},
|
|
],
|
|
}
|
|
|
|
result = client.get_run_tasks("run-123")
|
|
|
|
assert result.found is True
|
|
assert result.total_tasks == 3
|
|
assert result.failed_tasks == 0
|
|
assert result.completed_tasks == 3
|
|
assert len(result.tasks or []) == 3
|
|
assert len(result.failed_task_details or []) == 0
|
|
|
|
|
|
def test_get_run_tasks_mixed_failure() -> None:
|
|
"""Test get_run_tasks with a mix of successful and failed tasks."""
|
|
client = FakeTracerClient()
|
|
client._get_response = {
|
|
"success": True,
|
|
"data": [
|
|
{"tool_name": "ls", "exit_code": "0", "runtime_ms": 100},
|
|
{
|
|
"tool_name": "grep",
|
|
"exit_code": "1",
|
|
"runtime_ms": 200,
|
|
"tool_cmd": "grep foo bar",
|
|
"reason": "pattern not found",
|
|
"explanation": "The file did not contain 'foo'",
|
|
},
|
|
],
|
|
}
|
|
|
|
result = client.get_run_tasks("run-123")
|
|
|
|
assert result.found is True
|
|
assert result.total_tasks == 2
|
|
assert result.failed_tasks == 1
|
|
assert result.completed_tasks == 1
|
|
|
|
assert result.failed_task_details is not None
|
|
failed = result.failed_task_details[0]
|
|
assert failed["tool_name"] == "grep"
|
|
assert failed["exit_code"] == "1"
|
|
assert failed["tool_cmd"] == "grep foo bar"
|
|
assert failed["reason"] == "pattern not found"
|
|
assert failed["explanation"] == "The file did not contain 'foo'"
|
|
|
|
|
|
def test_get_run_tasks_empty_payload() -> None:
|
|
"""Test get_run_tasks with an empty data payload."""
|
|
client = FakeTracerClient()
|
|
client._get_response = {"success": True, "data": []}
|
|
|
|
result = client.get_run_tasks("run-123")
|
|
|
|
assert result.found is False
|
|
|
|
|
|
def test_get_run_tasks_unsuccessful_response() -> None:
|
|
"""Test get_run_tasks with an unsuccessful API response."""
|
|
client = FakeTracerClient()
|
|
client._get_response = {"success": False, "error": "Not Found"}
|
|
|
|
result = client.get_run_tasks("run-123")
|
|
assert result.found is False
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("code", "expected_fail"),
|
|
[
|
|
("0", False),
|
|
("", False),
|
|
(None, False),
|
|
("1", True),
|
|
("127", True),
|
|
(2, True),
|
|
],
|
|
)
|
|
def test_get_run_tasks_exit_code_handling(code: Any, expected_fail: bool) -> None:
|
|
"""Test get_run_tasks with various exit code formats."""
|
|
client = FakeTracerClient()
|
|
client._get_response = {"success": True, "data": [{"tool_name": "test", "exit_code": code}]}
|
|
result = client.get_run_tasks("run-123")
|
|
assert (result.failed_tasks == 1) is expected_fail
|