diff --git a/tests/unit/test_moving_bodies.py b/tests/unit/test_moving_bodies.py index 3dab002..23a89aa 100644 --- a/tests/unit/test_moving_bodies.py +++ b/tests/unit/test_moving_bodies.py @@ -321,6 +321,29 @@ def test_failed_advance_fails_simulation(monkeypatch, failure): sim.run(1, stream=STREAM) +def test_failed_hold_step_blocks_the_direct_stepper(monkeypatch): + # No target is pending, so only the failure latch can refuse direct steps. + from CelerisLab.lbm.stepper import LBMStepper + sim, writes, motion = advancing_simulation(monkeypatch, fail="upload") + motion._on_failure = sim._fail_moving + launches = [] + kernels = SimpleNamespace(get_function=lambda name: lambda *a, **k: launches.append(name)) + cfg = SimpleNamespace(streaming="double_buffer", threads_per_block=128, is_d2q9=True, + nx=64, ny=32, nz=1) + field = SimpleNamespace(ddf_gpu="ddf", temp_gpu="temp", flag_gpu="flag", n_curved=0) + stepper = LBMStepper(field, kernels, cfg) + stepper.moving = sim.stepper.moving + sim.stepper = stepper + assert motion.pending is None and stepper.blocked is None + with pytest.raises(RuntimeError, match="upload failed"): + sim.run(2, stream=STREAM) # hold step + assert sim._failed is not None and stepper.blocked == sim._failed + with pytest.raises(RuntimeError, match="moving circle step failed"): + stepper.step(1, action_gpu=None, obs_gpu=None) + assert launches == [] and stepper.step_count == 0 + assert (field.ddf_gpu, field.temp_gpu) == ("ddf", "temp") + + def test_moving_tables_layout_and_attachment(monkeypatch): from CelerisLab.body.motion import MovingTables a = MovingCircle((50., 40.), 10., Translation((-1., 1., -3., 3.), .1))