docs/tests: state the S3a commit point; cover a failed hold-record upload
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d50b8ba1be
commit
c21a365eca
@@ -374,9 +374,13 @@ recorded as not runnable rather than replaced by another test.
|
||||
`MovingCircleLinks` (`u_w = u + omega x r` at the hit point) → static curved →
|
||||
`OneStep` → swap → force region → sensors → synchronize → read `no_donor` →
|
||||
commit (`applied := pending.offset`) → upload the hold record
|
||||
(`c_old = c_new = applied`, `u = 0`). Hold steps launch no M1 and are the
|
||||
S2a path. Any failure from the upload on marks the circles and the
|
||||
Simulation failed; nothing is committed.
|
||||
(`c_old = c_new = applied`, `u = 0`) → synchronize. Hold steps launch no M1
|
||||
and are the S2a path. Commit point: the advancing step-group sync plus a
|
||||
zero `no_donor` count; a failure before it commits nothing. The hold-record
|
||||
upload stages the next step after the commit: if it (or its sync) fails,
|
||||
`applied` already matches the moved device geometry, but the Simulation is
|
||||
still marked failed and refuses reuse. Any failure from the first upload on
|
||||
marks the circles and the Simulation failed.
|
||||
- M1 classifies with the old/new predicates only (no flag reads). Covered
|
||||
cells add raw `sum c G` / `sum G` of `G^{n-1}` to `cover_*` and become
|
||||
`SOLID|OBSTACLE|BC_CURVED`. Uncovered cells: donors are fluid in both
|
||||
|
||||
@@ -254,7 +254,8 @@ class Tables:
|
||||
def upload_records(self, circles, stream):
|
||||
records = [m.record() for m, _ in circles]
|
||||
self.log.append(("upload", records))
|
||||
if self.fail == "upload":
|
||||
uploads = sum(1 for w in self.log if isinstance(w, tuple) and w[0] == "upload")
|
||||
if self.fail == "upload" or (self.fail == "hold_upload" and uploads == 2):
|
||||
raise RuntimeError("upload failed")
|
||||
return any(r[0] != r[1] for r in records)
|
||||
|
||||
@@ -294,15 +295,18 @@ def test_run_one_advances_and_commits_after_sync(monkeypatch):
|
||||
assert ("step", 3, False) in writes and motion.applied == (0., .25)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("failure", ("upload", "no_donor"))
|
||||
def test_failed_advance_commits_nothing_and_fails_simulation(monkeypatch, failure):
|
||||
kwargs = dict(fail="upload") if failure == "upload" else dict(no_donor=1.)
|
||||
@pytest.mark.parametrize("failure", ("upload", "no_donor", "hold_upload"))
|
||||
def test_failed_advance_fails_simulation(monkeypatch, failure):
|
||||
kwargs = dict(no_donor=1.) if failure == "no_donor" else dict(fail=failure)
|
||||
sim, writes, motion = advancing_simulation(monkeypatch, **kwargs)
|
||||
motion._on_failure = sim._fail_moving
|
||||
motion.set_target((0., .25), (0., .05))
|
||||
with pytest.raises(RuntimeError):
|
||||
sim.run(1, stream=STREAM)
|
||||
assert motion.applied == (0., 0.) and motion.failed and sim._failed is not None
|
||||
# Before the step-group sync nothing is committed; a failed hold-record upload
|
||||
# happens after the commit (applied already matches the moved device geometry).
|
||||
assert motion.applied == ((0., .25) if failure == "hold_upload" else (0., 0.))
|
||||
assert motion.failed and sim._failed is not None
|
||||
with pytest.raises(RuntimeError, match="Simulation failed"):
|
||||
sim.run(1, stream=STREAM)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user