"""Unit tests for engine.py's pure continuation planning — the source-length -> mask-bounds + total-length-cap math. No model, no GPU: `plan_continuation` is a pure function, so these run anywhere torch+numpy import.""" import pytest import engine def test_normal_request_maps_to_tail_mask(): total, new, mstart, mend = engine.plan_continuation(30, 60) assert total == 60 assert new == 30 # the mask runs from where the source ends to the total length assert mstart == 30 assert mend == 60 def test_total_capped_at_120(): total, new, mstart, mend = engine.plan_continuation(30, 200) assert total == engine.MAX_TOTAL_SECONDS == 120 assert new == 90 assert mstart == 30 and mend == 120 def test_min_new_floor_enforced(): # asking for barely-longer-than-source still generates at least MIN_NEW total, new, mstart, mend = engine.plan_continuation(30, 31) assert new == engine.MIN_NEW_SECONDS == 5 assert total == 35 assert mstart == 30 and mend == 35 def test_mask_always_brackets_the_new_region(): for src, req in [(15, 40), (29.5, 60), (50, 90), (10, 120)]: total, new, mstart, mend = engine.plan_continuation(src, req) assert mstart == src # mask starts at the seam assert mend == total # …and runs to the end assert abs((mend - mstart) - new) < 1e-6 # masked span == new audio assert total <= engine.MAX_TOTAL_SECONDS def test_source_at_max_keeps_min_new(): # the longest allowed clip still gets exactly MIN_NEW of continuation total, new, mstart, mend = engine.plan_continuation(engine.MAX_SOURCE_SECONDS, 130) assert total == engine.MAX_TOTAL_SECONDS == 120 assert new == engine.MIN_NEW_SECONDS == 5 assert mend > mstart # mask never inverts def test_overlong_source_raises_not_inverts(): # the old bug: source >= cap produced an inverted mask and a silent # no-op continuation. now it must raise instead. for src in (116, 120, 125, 200): with pytest.raises(ValueError): engine.plan_continuation(src, 60) def test_no_plan_ever_inverts_the_mask(): for src in [1, 15, 29.5, 60, 90, 110, 115]: total, new, mstart, mend = engine.plan_continuation(src, 60) assert mend > mstart # mask_end strictly after mask_start assert new >= engine.MIN_NEW_SECONDS - 1e-6 def test_constants_match_sa3_contract(): assert engine.SR == 44100 assert engine.STEPS == 8 assert engine.SAMPLER == "pingpong" assert engine.MAX_TOTAL_SECONDS == 120