fix(work): import hashlib and wire heal subparser into main CLI
This commit is contained in:
@@ -18,6 +18,7 @@ import tempfile
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timezone
|
||||
from unittest.mock import patch
|
||||
|
||||
REPO_ROOT = Path("/home/super/Projects/NetVM")
|
||||
BIN_DIR = REPO_ROOT / "bin"
|
||||
@@ -27,6 +28,39 @@ sys.path.insert(0, str(BIN_DIR))
|
||||
import gravity
|
||||
|
||||
|
||||
def _load(name, relpath):
|
||||
import importlib.util
|
||||
spec = importlib.util.spec_from_file_location(name, REPO_ROOT / relpath)
|
||||
mod = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(mod)
|
||||
return mod
|
||||
|
||||
|
||||
box_ctl = _load("box_ctl_loophealthtest", "bin/box-ctl.py")
|
||||
|
||||
|
||||
class _InProcResult:
|
||||
"""Minimal CompletedProcess stand-in (returncode/stdout only)."""
|
||||
|
||||
def __init__(self, returncode, stdout):
|
||||
self.returncode = returncode
|
||||
self.stdout = stdout
|
||||
|
||||
|
||||
def _box_ctl_inproc(*args):
|
||||
"""In-process box-ctl call (proven pattern from test_box_loop_https)."""
|
||||
import io
|
||||
from contextlib import redirect_stdout
|
||||
buf = io.StringIO()
|
||||
returncode = 0
|
||||
with redirect_stdout(buf):
|
||||
try:
|
||||
box_ctl.main(["box-ctl.py", *args])
|
||||
except SystemExit as e:
|
||||
returncode = e.code if isinstance(e.code, int) else 1
|
||||
return _InProcResult(returncode, buf.getvalue())
|
||||
|
||||
|
||||
class TestLoopDiagnosticsAndRemediation(unittest.TestCase):
|
||||
"""Test gravity.py loop health and progressive remediation."""
|
||||
|
||||
@@ -61,13 +95,27 @@ class TestLoopDiagnosticsAndRemediation(unittest.TestCase):
|
||||
self.assertIsInstance(res.get("remediated"), list)
|
||||
self.assertIsInstance(res.get("escalated"), list)
|
||||
|
||||
def test_remediate_single_approval_scan(self):
|
||||
import approvals
|
||||
real = approvals.check_fleet_approvals
|
||||
with patch.object(approvals, "check_fleet_approvals", wraps=real) as spy:
|
||||
res = gravity.remediate_breaks(dry_run=True)
|
||||
self.assertTrue(res.get("ok"))
|
||||
self.assertEqual(spy.call_count, 1)
|
||||
|
||||
def test_remediate_single_loop_parse(self):
|
||||
real = gravity._load_loop_candidates
|
||||
with patch.object(gravity, "_load_loop_candidates", wraps=real) as spy:
|
||||
res = gravity.remediate_breaks(dry_run=True)
|
||||
self.assertTrue(res.get("ok"))
|
||||
self.assertEqual(spy.call_count, 1)
|
||||
|
||||
|
||||
class TestLoopRpc(unittest.TestCase):
|
||||
"""Test box-ctl.py allowlisted RPC actions for loops."""
|
||||
|
||||
def test_box_ctl_loop_health(self):
|
||||
cmd = [sys.executable, str(BOX_CTL), "loop-health"]
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
res = _box_ctl_inproc("loop-health")
|
||||
self.assertEqual(res.returncode, 0)
|
||||
data = json.loads(res.stdout)
|
||||
self.assertTrue(data.get("ok"))
|
||||
@@ -76,16 +124,14 @@ class TestLoopRpc(unittest.TestCase):
|
||||
|
||||
|
||||
def test_box_ctl_loop_status(self):
|
||||
cmd = [sys.executable, str(BOX_CTL), "loop-status", "--limit", "5"]
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
res = _box_ctl_inproc("loop-status", "--limit", "5")
|
||||
self.assertEqual(res.returncode, 0)
|
||||
data = json.loads(res.stdout)
|
||||
self.assertTrue(data.get("ok"))
|
||||
self.assertIn("loops", data)
|
||||
|
||||
def test_box_ctl_loop_remediate_dry_run(self):
|
||||
cmd = [sys.executable, str(BOX_CTL), "loop-remediate", "--dry-run"]
|
||||
res = subprocess.run(cmd, capture_output=True, text=True)
|
||||
res = _box_ctl_inproc("loop-remediate", "--dry-run")
|
||||
self.assertEqual(res.returncode, 0)
|
||||
data = json.loads(res.stdout)
|
||||
self.assertTrue(data.get("ok"))
|
||||
|
||||
Reference in New Issue
Block a user