MAINT-14 review: tests for a HOLD episode after a no-SoC charge, a MAINT-13 state file, and a true twin site at N=2
checks / unit (pull_request) Successful in 34m56s
infra-pin / fresh (pull_request) Successful in 1s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 22:14:26 +02:00
co-authored by Claude Opus 5.5
parent ef35f4b925
commit 61a61941bb
+26 -2
View File
@@ -262,6 +262,13 @@ _, _, out, ev = run(m, T0, CHARGE_TIMEOUT_MIN + 10, None)
fail = [e for e in ev if "ABORT" in e]
check("charge-time limit: the reason gives the hours of charging time",
len(fail) == 1 and "36 h of charging time" in fail[0])
m = in_charge()
run(m, T0, 10, 98.0)
_, _, out, _ = run(m, T0 + 10 * MIN, CHARGE_TIMEOUT_MIN + 20, None)
_, _, _, ev = run(m, out[1] + MIN, 30, None)
check("charge done with no SoC, then HOLD with no SoC: a new episode, so the "
"HOLD line is said", out[0].phase == HOLD
and sum("hold waits" in e for e in ev) == 1)
print("6. restart while the SoC is missing")
with tempfile.TemporaryDirectory() as d:
@@ -307,19 +314,36 @@ with tempfile.TemporaryDirectory() as d:
res, _, out, _ = run(mo, T0, 120, None)
check("an old state file with no SoC seen: the charge fails at 36 h",
out and out[0].failed == "charge")
# a MAINT-13 state file: charge_track with a best but no `last`
since = (T0 - timedelta(hours=35)).isoformat()
m13 = dict(old, phase_started=since, charge_track={
"since": since, "open_min": 2100.0, "flat_min": 0.0, "best": 99.0,
"at": (T0 - MIN).isoformat()})
path4 = os.path.join(d, "s4.json")
json.dump(m13, open(path4, "w"))
mo = Maintenance(CFG, Store(path4))
res, _, out, _ = run(mo, T0, 120, None)
check("a MAINT-13 state file (no last SoC): no crash, the charge fails at "
"36 h (best is not last)", out and out[0].failed == "charge")
print("7. two packs")
a, b = (Maintenance(CFG, Mem(), unit="inverter-a", name="inverter-a"),
Maintenance(CFG, Mem(), unit="inverter-b", name="inverter-b"))
a.force_start(T0)
b_alone = Maintenance(CFG, Mem(), unit="inverter-b", name="inverter-b")
# the twin site: the same two packs, A healthy (SoC 60, still above the floor)
a_ok, b_alone = (Maintenance(CFG, Mem(), unit="inverter-a", name="inverter-a"),
Maintenance(CFG, Mem(), unit="inverter-b", name="inverter-b"))
a_ok.force_start(T0)
same = True
for i in range(0, 120, 10):
t = T0 + i * MIN
plan = arbitrate([a, b], t)
plan0 = arbitrate([a_ok, b_alone], t)
same = same and plan[1] == plan0[1]
ra = a.tick(t, None, blocked_by=plan[0])
rb = b.tick(t, 55.0, blocked_by=plan[1])
rb0 = b_alone.tick(t, 55.0, blocked_by=plan[1])
a_ok.tick(t, 60.0, blocked_by=plan0[0])
rb0 = b_alone.tick(t, 55.0, blocked_by=plan0[1])
same = same and (rb.phase, rb.setpoint_w, rb.deferred) == \
(rb0.phase, rb0.setpoint_w, rb0.deferred)
check("A drains with no SoC at 0 W while B (SoC 55, idle) is as it is when A "