Spaces:
Sleeping
Sleeping
| """Tests for ``training.rollout_buffer``. | |
| Round-trip add/get, group-sampling contract, clear-empties-buffer. | |
| """ | |
| from __future__ import annotations | |
| import random | |
| import pytest | |
| from training.rollout_buffer import RolloutBuffer, TrajectoryStep | |
| def _make_step(reward: float = 0.5, done: bool = False) -> TrajectoryStep: | |
| return TrajectoryStep( | |
| obs={"tick": 0, "regions": []}, | |
| action={"kind": "no_op"}, | |
| reward=reward, | |
| log_prob=None, | |
| done=done, | |
| ) | |
| def test_rollout_buffer_round_trip() -> None: | |
| """add_step β get_episode round-trips without data loss.""" | |
| buf = RolloutBuffer() | |
| s1 = _make_step(reward=0.3) | |
| s2 = _make_step(reward=0.7, done=True) | |
| buf.add_step("ep-A", s1) | |
| buf.add_step("ep-A", s2) | |
| out = buf.get_episode("ep-A") | |
| assert out == [s1, s2] | |
| assert buf.get_episode("missing-id") == [] | |
| def test_rollout_buffer_episode_return_sums_rewards() -> None: | |
| """episode_return == sum of step rewards.""" | |
| buf = RolloutBuffer() | |
| buf.add_step("ep", _make_step(reward=0.1)) | |
| buf.add_step("ep", _make_step(reward=-0.2)) | |
| buf.add_step("ep", _make_step(reward=0.5)) | |
| assert abs(buf.episode_return("ep") - 0.4) < 1e-9 | |
| def test_rollout_buffer_sample_group_is_deterministic_with_seed() -> None: | |
| """Same seed β same sample; different seed β likely different sample. | |
| Locks GRPO group-sampling determinism for trainer reproducibility. | |
| """ | |
| buf = RolloutBuffer() | |
| for i in range(8): | |
| buf.add_step(f"ep-{i}", _make_step()) | |
| rng_a = random.Random(42) | |
| rng_b = random.Random(42) | |
| sample_a = sorted(buf.sample_group(4, rng=rng_a)) | |
| sample_b = sorted(buf.sample_group(4, rng=rng_b)) | |
| assert sample_a == sample_b | |
| assert len(set(sample_a)) == 4 # no duplicates | |
| def test_rollout_buffer_sample_group_oversize_raises() -> None: | |
| """Requesting more episodes than buffer holds β ValueError.""" | |
| buf = RolloutBuffer() | |
| buf.add_step("ep-0", _make_step()) | |
| with pytest.raises(ValueError, match="exceeds buffer size"): | |
| buf.sample_group(5) | |
| def test_rollout_buffer_clear_empties_state() -> None: | |
| """clear() empties the buffer; len β 0.""" | |
| buf = RolloutBuffer() | |
| for i in range(3): | |
| buf.add_step(f"ep-{i}", _make_step()) | |
| assert len(buf) == 3 | |
| buf.clear() | |
| assert len(buf) == 0 | |
| assert buf.episode_ids() == [] | |