"""9.5-code track: code-reachable items only. - Parse unification: agent_tools / tool_approvals column parsing lives only in agent_def.py; server keeps None (undeclared), worker maps None to [] / {} at the _task_from_row boundary. - Goal branch of _apply_resume_preamble is reachable (via _goal_convert_queued on a queued auto-resumed task), so it is kept and tested, not deleted as dead code. - Fail-open inventory: audit write failure and preamble lookup failure log a warning without breaking dispatch. - M7: shadow endpoint explicit_capability_failures_truncated flag. - Policy content fingerprint: stable for the same document, changes when requires change, never touches audit rows. Run: python3 -m unittest discover -s cloud/tests -p "test_95_code.py" -v No real models, no network, no real gateway, no real PG. """ import http.client import json import os import sqlite3 import sys import tempfile import threading import time import unittest from types import SimpleNamespace from unittest import mock sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..")) import cloud.worker as worker_module from cloud.agent_def import ( parse_agent_tool_approvals_column, parse_agent_tools_column, ) from cloud.attempts import ensure_attempts_table, record_attempt from cloud.auth import AuthStore from cloud.models import parse_routing_policy from cloud.routing_dryrun import dry_run_policy_document from cloud.server import ( _agent_tool_approvals_from_row, _agent_tools_from_row, create_server, init_db, ) from cloud.worker import ( Worker, _agent_tool_approvals_from_col, _agent_tools_from_col, ) class ParseUnificationTestCase(unittest.TestCase): def test_shared_parser_is_single_source(self): # Missing / dirty / wrong-type all parse to None. for raw in (None, "not json", '{"a": 1}', '["a", 1]', 42): if raw == '["a", 1]': # A JSON list parses even if items are not strings; # the parser only guarantees list shape, not items. self.assertEqual(parse_agent_tools_column(raw), ["a", 1]) continue self.assertIsNone(parse_agent_tools_column(raw)) for raw in (None, "not json", '["a"]', '{"a": 1}', 42): if raw == '{"a": 1}': self.assertEqual( parse_agent_tool_approvals_column(raw), {"a": 1}) continue self.assertIsNone(parse_agent_tool_approvals_column(raw)) # Valid values are copied, not aliased. src = ["websearch"] self.assertEqual(parse_agent_tools_column(src), src) self.assertIsNot(parse_agent_tools_column(src), src) src = {"websearch": "ask"} self.assertEqual(parse_agent_tool_approvals_column(src), src) self.assertIsNot(parse_agent_tool_approvals_column(src), src) def test_server_keeps_none_worker_maps_to_empty(self): # Server serialization: missing/dirty stays None (undeclared). self.assertIsNone(_agent_tools_from_row({})) self.assertIsNone(_agent_tools_from_row({"agent_tools": "junk"})) self.assertEqual( _agent_tools_from_row({"agent_tools": '["websearch"]'}), ["websearch"]) self.assertIsNone(_agent_tool_approvals_from_row({})) self.assertIsNone( _agent_tool_approvals_from_row( {"agent_tool_approvals": "junk"})) # Worker dispatch: same parse, None mapped to [] / {}. self.assertEqual(_agent_tools_from_col(None), []) self.assertEqual(_agent_tools_from_col("junk"), []) self.assertEqual(_agent_tools_from_col('["websearch"]'), ["websearch"]) self.assertEqual(_agent_tool_approvals_from_col(None), {}) self.assertEqual(_agent_tool_approvals_from_col("junk"), {}) self.assertEqual( _agent_tool_approvals_from_col('{"websearch": "ask"}'), {"websearch": "ask"}) def _insert_task(db_path, task_id, prompt="做活", status="queued", project_id="p1", **cols): now = time.time() conn = sqlite3.connect(db_path) try: base = {"id": task_id, "project_id": project_id, "prompt": prompt, "status": status, "idempotency_key": None, "depends_on": "[]", "priority": 0, "created_by": "tester", "created_at": now, "updated_at": now, "last_heartbeat": None} base.update(cols) keys = list(base.keys()) conn.execute( "INSERT INTO tasks(%s) VALUES(%s)" % (", ".join(keys), ", ".join("?" * len(keys))), [base[k] for k in keys]) conn.commit() finally: conn.close() class WorkerCase(unittest.TestCase): def setUp(self): self.tmp = tempfile.TemporaryDirectory() self.db_path = os.path.join(self.tmp.name, "control.db") init_db(self.db_path) self.env = {"XCM_API_KEY": "test-placeholder"} def tearDown(self): self.tmp.cleanup() def _worker(self): def _runner(cmd): return SimpleNamespace(returncode=0, stdout="{}", stderr="") return Worker(self.db_path, "/fake/host.py", runner=_runner, env=self.env) class GoalBranchTestCase(WorkerCase): def test_goal_branch_reached_for_converted_goal_task(self): # Reachability proof (9.5-code): a non-goal task auto-resumed # as platform_fresh (count=1, queued) that is then converted # to a goal while still queued reaches the goal branch: # no _resume (resume_message was cleared by auto_resume), # no _goal_resume_breakpoint, count>0, latest attempt fresh. _insert_task(self.db_path, "t1", prompt="做活", goal="做目标", goal_mode=1, auto_resume_count=1) conn = sqlite3.connect(self.db_path) try: ensure_attempts_table(conn) record_attempt(conn, "t1", 1, "platform_fresh", "worker_shutdown", -1, "做到一半:已建 a.py", "被平台杀掉") conn.commit() finally: conn.close() worker = self._worker() task = worker.get_task("t1") injected = worker._apply_resume_preamble(task) self.assertIn("上次尝试说明", injected["goal"]) self.assertTrue(injected["goal"].endswith("做目标")) self.assertIn("上次尝试说明", injected["prompt"]) self.assertTrue(injected["prompt"].endswith("做活")) # Memory only: the stored goal is untouched. conn = sqlite3.connect(self.db_path) try: row = conn.execute("SELECT goal FROM tasks WHERE id = ?", ("t1",)).fetchone() finally: conn.close() self.assertEqual(row[0], "做目标") class FailOpenLogTestCase(WorkerCase): def test_audit_failure_logs_without_breaking_dispatch(self): worker = self._worker() calls = [] with mock.patch.object( worker_module, "AuthStore", side_effect=RuntimeError("db down")), \ mock.patch.object( worker_module, "log_event", side_effect=lambda *a, **k: calls.append(a[1])): # Must not raise: audit is best-effort by design. worker._audit("p1", "worker_claim", "t1") self.assertEqual(calls, ["worker_audit_failed"]) def test_preamble_lookup_failure_logs_and_returns_task(self): worker = self._worker() task = {"id": "t1", "project_id": "p1", "prompt": "做活", "auto_resume_count": 1} calls = [] with mock.patch.object( worker_module, "_db_connect", side_effect=RuntimeError("db down")), \ mock.patch.object( worker_module, "log_event", side_effect=lambda *a, **k: calls.append(a[1])): out = worker._apply_resume_preamble(task) self.assertIs(out["prompt"], "做活") self.assertEqual( calls, ["worker_resume_preamble_lookup_failed"]) class FingerprintTestCase(unittest.TestCase): def test_stable_and_sensitive_to_requires(self): doc = {"mode": "shadow", "tiers": {"default": "m1"}, "model_capabilities": {"m1": {"tool_calling": True}}} a = parse_routing_policy(doc) b = parse_routing_policy( {"model_capabilities": {"m1": {"tool_calling": True}}, "tiers": {"default": "m1"}, "mode": "shadow"}) self.assertEqual(a.content_fingerprint(), b.content_fingerprint()) c = parse_routing_policy({ "mode": "shadow", "tiers": {"default": {"model": "m1", "requires": {"tool_calling": True}}}, "model_capabilities": {"m1": {"tool_calling": True}}}) self.assertNotEqual(a.content_fingerprint(), c.content_fingerprint()) # Operator version string does not affect the fingerprint. d = parse_routing_policy(dict(doc, version="v99")) self.assertEqual(a.content_fingerprint(), d.content_fingerprint()) # Dry-run surfaces it; audit rows never carry it. report = dry_run_policy_document(doc) self.assertEqual(report["content_fingerprint"], a.content_fingerprint()) class _HttpServerCase(unittest.TestCase): def setUp(self): self._old = {k: os.environ.get(k) for k in ( "CLOUD_ROUTING_POLICY_JSON", "CLOUD_ROUTING_POLICY_FILE")} os.environ.pop("CLOUD_ROUTING_POLICY_JSON", None) os.environ.pop("CLOUD_ROUTING_POLICY_FILE", None) self.tmp = tempfile.TemporaryDirectory() self.db_path = os.path.join(self.tmp.name, "control.db") self.auth = AuthStore(self.db_path) self.owner_id, self.owner_key = self.auth.create_user("owner") self.server = create_server(self.db_path, "127.0.0.1", 0) self.port = self.server.server_address[1] self.thread = threading.Thread( target=self.server.serve_forever, daemon=True) self.thread.start() def tearDown(self): self.server.shutdown() self.server.server_close() self.thread.join(timeout=5) for k, v in self._old.items(): if v is None: os.environ.pop(k, None) else: os.environ[k] = v try: self.auth.conn.close() except Exception: pass self.tmp.cleanup() def _req(self, method, path, body=None, key=None): conn = http.client.HTTPConnection( "127.0.0.1", self.port, timeout=10) hdrs = {} payload = None if body is not None: payload = json.dumps(body).encode("utf-8") hdrs["Content-Type"] = "application/json" if key is not None: hdrs["X-API-Key"] = key try: conn.request(method, path, body=payload, headers=hdrs) resp = conn.getresponse() data = resp.read() finally: conn.close() try: parsed = json.loads(data.decode("utf-8")) if data else None except ValueError: parsed = None return resp.status, parsed def _project(self, name="p"): status, project = self._req( "POST", "/projects", {"name": name, "auto_pr": 1}, self.owner_key) self.assertEqual(status, 201, project) return project["id"] class ExplicitTruncationTestCase(_HttpServerCase): def test_explicit_failures_truncated_flag(self): pid = self._project() conn = sqlite3.connect(self.db_path) try: conn.executemany( "INSERT INTO audit_log(user_id, project_id, action," " detail, created_at) VALUES(?, ?, ?, ?, ?)", [("tester", pid, "worker_capability_gateway_explicit", "E1 model=m1 tier=default mode=active" " missing=tool_calling unknown=False blocked=True", time.time())] * 10001) conn.commit() finally: conn.close() status, report = self._req( "GET", "/routing-shadow?project_id=" + pid, key=self.owner_key) self.assertEqual(status, 200, report) self.assertTrue( report["explicit_capability_failures_truncated"]) self.assertEqual( len(report["explicit_capability_failures"]), 10000)