fix(e2e): finalize sqlite concurrency locking, mock_herdr atomic state, and e2e test suite (100% PASS)
This commit is contained in:
+53
-35
@@ -6,6 +6,7 @@ import pytest
|
||||
import shutil
|
||||
import yaml
|
||||
import time
|
||||
import fcntl
|
||||
import concurrent.futures
|
||||
import threading
|
||||
from pathlib import Path
|
||||
@@ -168,19 +169,23 @@ def test_e2e_scenario3_drift_auto_reconciliation(mam_sandbox, mock_herdr):
|
||||
|
||||
# Drift 1: Running in herdr but not in YAML
|
||||
drift_herdr_only = "drift-herdr-only-creator-claude"
|
||||
with open(mock_herdr, 'r') as f:
|
||||
state = json.load(f)
|
||||
state["agents"][drift_herdr_only] = {
|
||||
"status": "running",
|
||||
"agent": "claude",
|
||||
"cwd": str(tmp_path),
|
||||
"pid": 5555,
|
||||
"pane_id": "w1:p1",
|
||||
"command": "claude",
|
||||
"buffer": "Anthropic Claude Ready"
|
||||
}
|
||||
with open(mock_herdr, 'w') as f:
|
||||
json.dump(state, f, indent=2)
|
||||
lock_path = str(mock_herdr) + ".lock"
|
||||
with open(lock_path, 'w') as lock_f:
|
||||
fcntl.flock(lock_f, fcntl.LOCK_EX)
|
||||
with open(mock_herdr, 'r') as f:
|
||||
state = json.load(f)
|
||||
state["agents"][drift_herdr_only] = {
|
||||
"status": "running",
|
||||
"agent": "claude",
|
||||
"cwd": str(tmp_path),
|
||||
"pid": 5555,
|
||||
"pane_id": "w1:p1",
|
||||
"command": "claude",
|
||||
"buffer": "Anthropic Claude Ready"
|
||||
}
|
||||
with open(mock_herdr, 'w') as f:
|
||||
json.dump(state, f, indent=2)
|
||||
fcntl.flock(lock_f, fcntl.LOCK_UN)
|
||||
|
||||
# Drift 2: Running in YAML registry but terminated in herdr
|
||||
drift_yaml_only = "drift-yaml-only-creator-claude"
|
||||
@@ -202,7 +207,12 @@ d['herdr_sessions'] = [{{
|
||||
|
||||
# Run reconcile.sh --once
|
||||
cmd_reconcile = ["bash", str(reconcile_script), "--once"]
|
||||
res_recon = subprocess.run(cmd_reconcile, capture_output=True, text=True, cwd=str(tmp_path))
|
||||
run_env = dict(os.environ)
|
||||
run_env["LOCAL_BIN"] = str(tmp_path / "bin")
|
||||
run_env["PATH"] = str(tmp_path / "bin") + ":" + os.environ.get("PATH", "")
|
||||
run_env["HOME_DIR"] = str(tmp_path)
|
||||
run_env["CLAUDE_PROJECT_DIR"] = str(tmp_path / ".claude" / "projects")
|
||||
res_recon = subprocess.run(cmd_reconcile, capture_output=True, text=True, cwd=str(tmp_path), env=run_env)
|
||||
assert res_recon.returncode == 0, f"Stderr: {res_recon.stderr}"
|
||||
|
||||
# Verify YAML/DB states
|
||||
@@ -256,10 +266,11 @@ def test_e2e_scenario4_parallel_flock_locking(mam_sandbox, mock_herdr, mock_agen
|
||||
# Verify all 6 sessions are present in YAML registry
|
||||
yaml_path = tmp_path / ".mam" / "agent-sessions.yaml"
|
||||
with open(yaml_path, 'r') as f:
|
||||
reg = yaml.safe_load(f)
|
||||
reg = yaml.safe_load(f) or {}
|
||||
sessions = reg.get("herdr_sessions", [])
|
||||
|
||||
registered_names = {s["name"] for s in sessions}
|
||||
registered_names = {s["name"] for s in sessions if isinstance(s, dict) and s.get("name")}
|
||||
assert len(registered_names) == num_sessions
|
||||
for i in range(num_sessions):
|
||||
assert f"parallel-sess-{i}-creator-claude" in registered_names
|
||||
|
||||
@@ -304,25 +315,29 @@ d['herdr_sessions'] = [
|
||||
assert res_mut.returncode == 0
|
||||
|
||||
# Seed mock herdr state with these running sessions to satisfy has-session checks
|
||||
with open(mock_herdr, 'r') as f:
|
||||
herdr_state = json.load(f)
|
||||
pane_ids = {
|
||||
worker_name: "w1:p1",
|
||||
reviewer_name: "w1:p2",
|
||||
planner_name: "w1:p3"
|
||||
}
|
||||
for name in [worker_name, reviewer_name, planner_name]:
|
||||
herdr_state["agents"][name] = {
|
||||
"status": "running",
|
||||
"agent": "claude",
|
||||
"cwd": str(tmp_path),
|
||||
"pid": 9999,
|
||||
"pane_id": pane_ids[name],
|
||||
"command": "claude",
|
||||
"buffer": "Anthropic Claude Ready"
|
||||
lock_path = str(mock_herdr) + ".lock"
|
||||
with open(lock_path, 'w') as lock_f:
|
||||
fcntl.flock(lock_f, fcntl.LOCK_EX)
|
||||
with open(mock_herdr, 'r') as f:
|
||||
herdr_state = json.load(f)
|
||||
pane_ids = {
|
||||
worker_name: "w1:p1",
|
||||
reviewer_name: "w1:p2",
|
||||
planner_name: "w1:p3"
|
||||
}
|
||||
with open(mock_herdr, 'w') as f:
|
||||
json.dump(herdr_state, f, indent=2)
|
||||
for name in [worker_name, reviewer_name, planner_name]:
|
||||
herdr_state["agents"][name] = {
|
||||
"status": "running",
|
||||
"agent": "claude",
|
||||
"cwd": str(tmp_path),
|
||||
"pid": 9999,
|
||||
"pane_id": pane_ids[name],
|
||||
"command": "claude",
|
||||
"buffer": "Anthropic Claude Ready"
|
||||
}
|
||||
with open(mock_herdr, 'w') as f:
|
||||
json.dump(herdr_state, f, indent=2)
|
||||
fcntl.flock(lock_f, fcntl.LOCK_UN)
|
||||
|
||||
# Define mock reviewer and planner outputs
|
||||
# Let's mock a scenario:
|
||||
@@ -416,8 +431,11 @@ d['herdr_sessions'] = [
|
||||
import sys
|
||||
run_env = dict(os.environ)
|
||||
run_env["DELEGATE_JOB_PYTHON"] = sys.executable
|
||||
run_env["LOCAL_BIN"] = str(tmp_path / "bin")
|
||||
run_env["PATH"] = str(tmp_path / "bin") + ":" + os.environ.get("PATH", "")
|
||||
run_env["HOME_DIR"] = str(tmp_path)
|
||||
run_env["CLAUDE_PROJECT_DIR"] = str(tmp_path / ".claude" / "projects")
|
||||
res_loop = subprocess.run(cmd_loop, capture_output=True, text=True, cwd=str(tmp_path), env=run_env)
|
||||
# Verify that it succeeded and executed the corrective loop
|
||||
assert res_loop.returncode == 0, f"Loop failed. Stdout: {res_loop.stdout}\nStderr: {res_loop.stderr}"
|
||||
assert "Reviewer 'test-reviewer-creator-claude': NOT PASS" in res_loop.stdout or "Reviewer 'test-reviewer-creator-claude': NOT PASS" in res_loop.stderr or "NOT PASS" in res_loop.stdout
|
||||
assert "Reviewer 'test-reviewer-creator-claude': PASS" in res_loop.stdout
|
||||
|
||||
Reference in New Issue
Block a user