MAINT-13 review: tests for a stale charge record and a clock step back; DOCS names the 7 day end
checks / unit (pull_request) Successful in 34m49s
infra-pin / fresh (pull_request) Successful in 2s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 13:08:40 +02:00
co-authored by Claude Opus 5.5
parent 6836f61bd4
commit ea31289ec0
2 changed files with 19 additions and 1 deletions
+2 -1
View File
@@ -1672,7 +1672,8 @@ balances, so it need not reach `maintenance_soc_target`. The charge counts as
done when the battery is within 3 points of the target and has taken no more done when the battery is within 3 points of the target and has taken no more
charge for 60 minutes of charging time, or when the charging time (36 hours) runs charge for 60 minutes of charging time, or when the charging time (36 hours) runs
out within 3 points of the target. Only the minutes the cheap-hours gate let the out within 3 points of the target. Only the minutes the cheap-hours gate let the
battery charge count. Then the usual hold follows. battery charge count, and the charge ends after 7 days at the
latest. Then the usual hold follows.
**When a cycle fails.** If the battery does not empty in 12 hours, or does not **When a cycle fails.** If the battery does not empty in 12 hours, or does not
get within 3 points of the target in 36 hours of charging time, the cycle get within 3 points of the target in 36 hours of charging time, the cycle
+17
View File
@@ -240,6 +240,10 @@ check("a gap in the ticks (add-on down) counts for exactly 5 minutes (the cap)",
abs(m._trk["open_min"] - before - 5.0) < 1e-9) abs(m._trk["open_min"] - before - 5.0) < 1e-9)
m.tick(t + 2 * timedelta(hours=1) + 2 * MIN, 70.0) m.tick(t + 2 * timedelta(hours=1) + 2 * MIN, 70.0)
check("...and a 2 minute step counts 2", abs(m._trk["open_min"] - before - 7.0) < 1e-9) check("...and a 2 minute step counts 2", abs(m._trk["open_min"] - before - 7.0) < 1e-9)
_t = t + 2 * timedelta(hours=1) + 2 * MIN
m.tick(_t - 10 * MIN, 70.0) # the clock steps back 10 min
check("...and a step back in time counts nothing (not minus)",
abs(m._trk["open_min"] - before - 7.0) < 1e-9)
print("6. restarts and old state files") print("6. restarts and old state files")
with tempfile.TemporaryDirectory() as d: with tempfile.TemporaryDirectory() as d:
@@ -286,6 +290,19 @@ with tempfile.TemporaryDirectory() as d:
res, _, out = run(mo, T0 + MIN, 120, 70.0) res, _, out = run(mo, T0 + MIN, 120, 70.0)
check("...so it fails when the 36 h are up, as before", check("...so it fails when the 36 h are up, as before",
out and out[0].failed == "charge") out and out[0].failed == "charge")
# A record left by another charge (an add-on rolled back and forward
# again does not clear it) must not be read as this charge's.
stale = {"phase": "charge",
"phase_started": (T0 - timedelta(hours=2)).isoformat(),
"charge_track": {"since": (T0 - timedelta(days=30)).isoformat(),
"open_min": 2000.0, "flat_min": 59.0,
"best": 99.0, "at": None}}
ms = Maintenance(CFG, Mem(stale))
r = ms.tick(T0, 98.0)
check("a charge record from another charge is ignored: this charge counts "
"its own 2 h and its own best",
r.phase == CHARGE and 119 < ms._trk["open_min"] < 121
and ms._trk["flat_min"] == 0.0 and ms._trk["best"] == 98.0)
mi = Maintenance(CFG, Store(os.path.join(d, "none.json"))) mi = Maintenance(CFG, Store(os.path.join(d, "none.json")))
check("no state file: due, no back-off", mi.due(T0) and mi.backoff_until(T0) is None) check("no state file: due, no back-off", mi.due(T0) and mi.backoff_until(T0) is None)