Files
tracer-cloud--opensre/tests/interactive_shell/runtime/test_session.py
T
wehub-resource-sync 4b6817381b
Benchmark image — build + push to ECR (any adapter) / build + push (push) Waiting to run
CI / quality (ubuntu-latest) (push) Waiting to run
CI / test (tools-runtime) (push) Waiting to run
CI / test (e2e-general) (push) Waiting to run
CI / test (cli-runtime) (push) Waiting to run
CI / test (e2e-provider-and-openclaw) (push) Waiting to run
CI / test (integrations-and-misc) (push) Waiting to run
CI / coverage-report (push) Blocked by required conditions
CI / test-kubernetes (push) Waiting to run
CI / should-run-thorough (push) Waiting to run
CI / test-thorough (cloudwatch-demo) (push) Blocked by required conditions
CI / test-thorough (flink-ecs) (push) Blocked by required conditions
CI / test-thorough (upstream-lambda) (push) Blocked by required conditions
CI / test-thorough (prefect-ecs-fargate) (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Blocked by required conditions
Release / publish-release (push) Blocked by required conditions
Release / publish-main-release (push) Blocked by required conditions
Release / prepare (push) Waiting to run
Release / verify (push) Blocked by required conditions
Release / build-python-dist (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Blocked by required conditions
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Waiting to run
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

257 lines
10 KiB
Python

"""Tests for Session state."""
from __future__ import annotations
from pathlib import Path
import pytest
import config.constants as const_module
from config.constants.prompts import SUGGESTED_PROMPT_AFTER_FAILED_SYNTHETIC_TEST
from platform.common.task_registry import TaskRegistry
from platform.common.task_types import TaskKind
from surfaces.interactive_shell.session import (
Session,
)
from surfaces.interactive_shell.session.session import _scenario_id_from_synthetic_label
class TestSession:
def test_defaults(self) -> None:
session = Session()
assert session.history == []
assert session.last_state is None
assert session.accumulated_context == {}
assert session.terminal.trust_mode is False
assert session.task_registry.list_recent() == []
assert session.terminal.metrics.turn_count == 0
assert session.terminal.metrics.fallback_count == 0
assert session.terminal.metrics.ctrl_c_intervention_count == 0
assert session.terminal.metrics.correction_intervention_count == 0
assert session.terminal.pending_prompt_default is None
assert session.last_synthetic_observation_path is None
def test_take_pending_prompt_default_returns_and_clears(self) -> None:
session = Session()
session.terminal.pending_prompt_default = "why did it fail?"
assert session.terminal.pop_pending_prompt_default() == "why did it fail?"
assert session.terminal.pending_prompt_default is None
assert session.terminal.pop_pending_prompt_default() == ""
def test_clear_resets_pending_prompt_default(self) -> None:
session = Session()
session.terminal.pending_prompt_default = "why did it fail?"
session.clear()
assert session.terminal.pending_prompt_default is None
def test_queue_auto_command_sets_pending_and_notifies(self) -> None:
session = Session()
calls: list[bool] = []
session.terminal.prompt_refresh_fn = lambda: calls.append(True)
session.terminal.set_auto_command("/integrations setup sentry")
assert session.terminal.pending_prompt_default == "/integrations setup sentry"
assert session.terminal.pending_prompt_autosubmit is True
assert calls == [True]
def test_take_pending_autosubmit_returns_and_clears(self) -> None:
session = Session()
session.terminal.pending_prompt_autosubmit = True
assert session.terminal.pop_pending_autosubmit() is True
assert session.terminal.pending_prompt_autosubmit is False
assert session.terminal.pop_pending_autosubmit() is False
def test_clear_resets_pending_autosubmit(self) -> None:
session = Session()
session.terminal.set_auto_command("/integrations setup sentry")
session.clear()
assert session.terminal.pending_prompt_autosubmit is False
assert session.terminal.pending_prompt_default is None
def test_scenario_id_from_synthetic_label(self) -> None:
assert (
_scenario_id_from_synthetic_label(
"opensre tests synthetic --scenario 001-replication-lag"
)
== "001-replication-lag"
)
assert _scenario_id_from_synthetic_label("rds_postgres:001-replication-lag") == (
"001-replication-lag"
)
assert _scenario_id_from_synthetic_label("opensre tests synthetic --scenario ./evil") == ""
assert _scenario_id_from_synthetic_label("rds_postgres:not-a-scenario") == ""
def test_suggest_synthetic_failure_follow_up_sets_pending(self) -> None:
session = Session()
session.suggest_synthetic_failure_follow_up(
label="opensre tests synthetic --scenario 001-replication-lag",
)
assert (
session.terminal.pending_prompt_default == SUGGESTED_PROMPT_AFTER_FAILED_SYNTHETIC_TEST
)
def test_record_appends_entry(self) -> None:
session = Session()
session.record("alert", "cpu high")
session.record("slash", "/status", ok=True)
session.record("alert", "bad one", ok=False)
assert len(session.history) == 3
assert session.history[-1]["type"] == "alert"
assert session.history[-1]["ok"] is False
def test_mark_latest_updates_most_recent_matching_kind(self) -> None:
session = Session()
session.record("slash", "/investigate missing.json")
session.record("alert", "missing.json", ok=False)
session.mark_latest(ok=False, kind="slash")
assert session.history[0]["ok"] is False
assert session.history[1]["ok"] is False
def test_clear_preserves_trust_mode(self) -> None:
session = Session()
session.terminal.trust_mode = True
session.terminal.background_notification_preferences.set_channels(["email"])
session.accumulated_context["service"] = "api"
session.record("alert", "something")
session.last_state = {"foo": "bar"}
session.agent.messages.append(("user", "hey"))
session.terminal.metrics.record_intervention("ctrl_c")
session.terminal.metrics.record_intervention("correction")
assert session.terminal.history_generation == 0
session.clear()
assert session.terminal.history_generation == 1
assert session.history == []
assert session.last_state is None
assert session.accumulated_context == {}
assert session.agent.messages == []
assert session.task_registry.list_recent() == []
assert session.terminal.metrics.ctrl_c_intervention_count == 0
assert session.terminal.metrics.correction_intervention_count == 0
assert session.terminal.background_notification_preferences.channels == ("email",)
assert session.terminal.trust_mode is True # preserved intentionally
def test_clear_keeps_persisted_task_history_file(
self,
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
session = Session()
monkeypatch.setattr(const_module, "OPENSRE_HOME_DIR", tmp_path)
session.task_registry = TaskRegistry.persistent()
task = session.task_registry.create(
TaskKind.SYNTHETIC_TEST, command="opensre tests synthetic"
)
task.mark_running()
session.clear()
reloaded = TaskRegistry.persistent()
loaded = reloaded.get(task.task_id)
assert loaded is not None
assert loaded.task_id == task.task_id
def test_accumulate_from_state_extracts_known_keys(self) -> None:
session = Session()
session.accumulate_from_state(
{
"service": "orders-api",
"pipeline_name": "events_fact",
"cluster_name": "prod-us-east",
"region": "us-east-1",
"environment": "production",
"root_cause": "disk full", # not accumulated
"evidence": {"ev-1": "x"}, # not accumulated
}
)
assert session.accumulated_context == {
"service": "orders-api",
"pipeline_name": "events_fact",
"cluster_name": "prod-us-east",
"region": "us-east-1",
"environment": "production",
}
def test_accumulate_from_state_skips_empty_and_none(self) -> None:
session = Session()
session.accumulate_from_state(
{
"service": "",
"cluster_name": None,
"region": "us-east-1",
}
)
assert session.accumulated_context == {"region": "us-east-1"}
def test_accumulate_from_state_merges_across_calls(self) -> None:
"""Subsequent investigations fill in context the earlier one didn't have."""
session = Session()
session.accumulate_from_state({"service": "orders-api"})
session.accumulate_from_state({"cluster_name": "prod-us-east"})
assert session.accumulated_context == {
"service": "orders-api",
"cluster_name": "prod-us-east",
}
def test_accumulate_from_state_handles_none_and_empty_state(self) -> None:
session = Session()
session.accumulate_from_state(None)
session.accumulate_from_state({})
assert session.accumulated_context == {}
def test_record_terminal_turn_updates_aggregates(self) -> None:
session = Session()
first = session.terminal.metrics.record_turn(
executed_count=2,
executed_success_count=1,
fallback_to_llm=True,
)
second = session.terminal.metrics.record_turn(
executed_count=1,
executed_success_count=1,
fallback_to_llm=False,
)
assert first.turn_index == 1
assert first.fallback_count == 1
assert first.action_success_percent == 50.0
assert first.fallback_rate_percent == 100.0
assert second.turn_index == 2
assert second.fallback_count == 1
assert round(second.action_success_percent, 2) == 66.67
assert second.fallback_rate_percent == 50.0
def test_record_intervention_increments_per_kind(self) -> None:
session = Session()
session.terminal.metrics.record_intervention("ctrl_c")
session.terminal.metrics.record_intervention("ctrl_c")
session.terminal.metrics.record_intervention("correction")
assert session.terminal.metrics.ctrl_c_intervention_count == 2
assert session.terminal.metrics.correction_intervention_count == 1
def test_record_intervention_kinds_are_independent(self) -> None:
"""Incrementing one kind does not touch the other."""
session = Session()
session.terminal.metrics.record_intervention("correction")
assert session.terminal.metrics.ctrl_c_intervention_count == 0
assert session.terminal.metrics.correction_intervention_count == 1
def test_fresh_session_starts_with_zero_intervention_counts(self) -> None:
"""A new Session does not inherit any prior session's counters."""
first = Session()
first.terminal.metrics.record_intervention("ctrl_c")
first.terminal.metrics.record_intervention("correction")
second = Session()
assert second.terminal.metrics.ctrl_c_intervention_count == 0
assert second.terminal.metrics.correction_intervention_count == 0