a2d238d92e
Make Zed Agent closer to Cursor: deterministic DevOps path index, live Traefik port probe before blind edits, stop-after-edit, and quieter Russian progress.
99 lines
3.3 KiB
Python
99 lines
3.3 KiB
Python
"""Unit tests for DevOps runtime_probe."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from runtime_probe import (
|
|
attach_runtime_probe,
|
|
devops_blocks_blind_force_edit,
|
|
extract_hosts,
|
|
is_devops_request,
|
|
suggested_traefik_edit,
|
|
)
|
|
|
|
|
|
class TestRuntimeProbe(unittest.TestCase):
|
|
def test_extract_hosts(self) -> None:
|
|
hosts = extract_hosts(
|
|
"observer.ift.calentiq.com не работает — Bad Gateway"
|
|
)
|
|
self.assertEqual(hosts, ["observer.ift.calentiq.com"])
|
|
|
|
def test_is_devops_request(self) -> None:
|
|
self.assertTrue(
|
|
is_devops_request(
|
|
{"user_goal": "fix traefik"},
|
|
"observer.ift.calentiq.com Bad Gateway",
|
|
)
|
|
)
|
|
self.assertFalse(is_devops_request({"user_goal": "rename button"}))
|
|
|
|
def test_attach_probe_sets_facts(self) -> None:
|
|
plan = {
|
|
"user_goal": "observer.ift.calentiq.com Bad Gateway",
|
|
"subtasks": [
|
|
{
|
|
"id": "1",
|
|
"prompt": "fix traefik",
|
|
"paths": [],
|
|
}
|
|
],
|
|
}
|
|
fake = {
|
|
"host": "observer.ift.calentiq.com",
|
|
"http_status": 502,
|
|
"service": "observer_web",
|
|
"ports": {"observer_web:80": False, "observer_web:4000": True},
|
|
"open_ports": [4000],
|
|
"suggested_backend_url": "http://observer_web:4000",
|
|
"hint": "port mismatch",
|
|
"source": "gateway_tcp",
|
|
"closed_port_80_but_alt_open": True,
|
|
}
|
|
with patch("runtime_probe.probe_host", return_value=fake):
|
|
out = attach_runtime_probe(
|
|
plan,
|
|
user_text="observer.ift.calentiq.com не работает",
|
|
cfg={"runtime_probe_enabled": True},
|
|
)
|
|
self.assertEqual(out["runtime_probe"], "gateway")
|
|
self.assertEqual(
|
|
out["runtime_facts"]["suggested_backend_url"],
|
|
"http://observer_web:4000",
|
|
)
|
|
self.assertIn("4000", out["subtasks"][0]["edit_goal"])
|
|
path0 = out["subtasks"][0]["paths"][0]
|
|
self.assertTrue(path0.endswith("dynamic_conf.yml"))
|
|
|
|
def test_suggested_traefik_edit(self) -> None:
|
|
plan = {
|
|
"runtime_facts": {
|
|
"service": "observer_web",
|
|
"suggested_backend_url": "http://observer_web:4000",
|
|
"hint": "x",
|
|
}
|
|
}
|
|
fix = suggested_traefik_edit(plan)
|
|
assert fix is not None
|
|
self.assertEqual(fix["old_text"], 'url: "http://observer_web:80"')
|
|
self.assertEqual(fix["new_text"], 'url: "http://observer_web:4000"')
|
|
|
|
def test_blocks_blind_without_facts(self) -> None:
|
|
plan = {"user_goal": "Bad Gateway traefik observer.ift.calentiq.com"}
|
|
self.assertTrue(devops_blocks_blind_force_edit(plan))
|
|
plan["runtime_facts"] = {"host": "x", "http_status": 502}
|
|
self.assertFalse(devops_blocks_blind_force_edit(plan))
|
|
|
|
def test_disabled(self) -> None:
|
|
plan = {"user_goal": "observer.ift.calentiq.com"}
|
|
out = attach_runtime_probe(
|
|
plan, user_text="x", cfg={"runtime_probe_enabled": False}
|
|
)
|
|
self.assertIsNone(out.get("runtime_facts"))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|