Files
tracer-cloud--opensre/tests/e2e/openclaw/test_gateway_down.py
T
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

108 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""End-to-end: OpenClaw Gateway is down — assert OpenSRE identifies it.
First fault scenario for #1484. Boots OpenClaw without the Gateway,
drives an MCP tool call (which fails because the bridge can't reach a
Gateway), captures the failure, then asserts the OpenSRE investigation
pipeline names "OpenClaw" + "gateway" and recommends starting it via
``openclaw gateway run``.
Skipped when:
- the ``openclaw`` CLI is not installed, OR
- Node 22.12+ is not available (OpenClaw won't run), OR
- no LLM credential is configured (RCA requires an LLM call)
The first two checks live in :mod:`infrastructure_sdk.local` via
:func:`boot_openclaw`. The LLM-credential check happens here so a
contributor can run ``make test-openclaw`` with just OpenClaw installed
and still see the use-case smoke pass.
"""
from __future__ import annotations
import pytest
from tests.e2e.openclaw.infrastructure_sdk.fault_injection import inject_gateway_down
from tests.e2e.openclaw.infrastructure_sdk.local import (
LLM_CREDENTIAL_SKIP_REASON,
OPENCLAW_CLI_SKIP_REASON,
boot_openclaw,
llm_credentials_present,
openclaw_cli_available,
teardown_openclaw,
)
from tests.e2e.openclaw.use_case import drive_openclaw_conversation
pytestmark = pytest.mark.e2e
@pytest.mark.skipif(not openclaw_cli_available(), reason=OPENCLAW_CLI_SKIP_REASON)
def test_gateway_down_use_case_captures_connection_failure() -> None:
"""Without a running Gateway, the MCP bridge cannot reach one and
``conversations_list`` fails.
This sub-test exercises the use_case + fault-injection wiring
without depending on an LLM. It locks in the failure-context dict
shape that ``orchestrator.run_openclaw_investigation`` consumes.
"""
handle = boot_openclaw(with_gateway=False)
try:
inject_gateway_down(handle)
context = drive_openclaw_conversation(handle)
finally:
teardown_openclaw(handle)
assert context["failure_mode"] == "gateway_down", context
assert context["transport_mode"] == "stdio"
assert context["command"] == "openclaw"
assert context["args"] == "mcp serve"
# The error string varies by environment (sometimes "Connection
# closed", sometimes "ECONNREFUSED", sometimes a stdio shutdown
# message). Assert the canonical gateway-unavailable hint surfaces
# in the detail rendered by ``describe_openclaw_error``.
detail = context["error_detail"].lower()
assert "openclaw" in detail
assert any(
marker in detail
for marker in ("connection closed", "econnrefused", "closed", "could not connect")
), context
@pytest.mark.skipif(not openclaw_cli_available(), reason=OPENCLAW_CLI_SKIP_REASON)
@pytest.mark.skipif(not llm_credentials_present(), reason=LLM_CREDENTIAL_SKIP_REASON)
def test_gateway_down_investigation_identifies_openclaw_and_remediation() -> None:
"""Run the full OpenSRE investigation against the captured failure
and assert the RCA correctly names OpenClaw + the gateway failure
mode + the remediation hint.
Real LLM call inside — count this as an integration cost when
running locally. Skipped when no LLM credential is configured.
"""
from tests.e2e.openclaw.orchestrator import run_openclaw_investigation, summarize_result
handle = boot_openclaw(with_gateway=False)
try:
inject_gateway_down(handle)
failure_context = drive_openclaw_conversation(handle)
assert failure_context["failure_mode"] == "gateway_down"
result = run_openclaw_investigation(handle, failure_context)
finally:
teardown_openclaw(handle)
summary = summarize_result(result)
assert "openclaw" in summary, result
# The RCA can legitimately attribute the failure at either the
# Gateway layer ("openclaw gateway down") or the bridge layer
# ("openclaw mcp bridge unreachable") — both identify the right
# OpenClaw subsystem and are correct readings of the captured
# ECONNREFUSED. Accept either.
assert ("gateway" in summary) or ("bridge" in summary), result
# Remediation should steer the user back to running the Gateway or
# restarting the bridge — either is a valid action that resolves
# the ECONNREFUSED failure. ``summary`` includes the report's
# "## Recommended Actions" section, so we check it directly.
assert ("openclaw gateway" in summary) or ("openclaw mcp" in summary), result
# Logged, not asserted: LLM-variance scores (~0.40.7) would flake a strict gate.
print(f"validity_score={result.get('validity_score', 0)} (logged, not asserted)")