verirl-env / tests /test_environment.py
Supreeth's picture
Upload folder using huggingface_hub
2b4ae64 verified
"""Tests for VerirlEnvironment."""
import pytest
from verirl_env.models import VerirlAction
from verirl_env.server.verirl_env_environment import VerirlEnvironment
class TestEnvironmentReset:
"""Test environment reset."""
def test_reset_mac_unit(self, environment):
obs = environment.reset(task_id="mac_unit")
assert obs.task_spec != ""
assert "mac" in obs.task_spec.lower()
assert obs.compile_ok is False
assert obs.tests_passed == 0
assert obs.turn_number == 0
assert obs.turns_remaining == 8
assert obs.done is False
def test_reset_axi_fifo(self, environment):
obs = environment.reset(task_id="axi_fifo")
assert obs.task_spec != ""
assert "fifo" in obs.task_spec.lower()
assert obs.turns_remaining == 10
def test_reset_systolic_array(self, environment):
obs = environment.reset(task_id="systolic_array")
assert obs.task_spec != ""
assert "systolic" in obs.task_spec.lower()
assert obs.turns_remaining == 12
def test_reset_random_task(self, environment):
obs = environment.reset(task_id=None)
assert obs.task_spec != ""
assert obs.turns_remaining > 0
class TestEnvironmentStep:
"""Test environment steps."""
def test_write_file_step(self, environment):
environment.reset(task_id="mac_unit")
obs = environment.step(VerirlAction(
action_type="write_file",
verilog_src="module mac_unit (input a); endmodule"
))
assert obs.current_verilog is not None
assert obs.turn_number == 1
assert obs.turns_remaining == 7
def test_write_empty_file(self, environment):
environment.reset(task_id="mac_unit")
obs = environment.step(VerirlAction(
action_type="write_file",
verilog_src=""
))
assert "ERROR" in obs.tool_stderr
def test_run_compile_no_file(self, environment):
environment.reset(task_id="mac_unit")
obs = environment.step(VerirlAction(action_type="run_compile"))
assert "ERROR" in obs.tool_stderr
def test_run_compile_after_write(self, environment, mac_reference_verilog, requires_iverilog):
environment.reset(task_id="mac_unit")
environment.step(VerirlAction(
action_type="write_file",
verilog_src=mac_reference_verilog
))
obs = environment.step(VerirlAction(action_type="run_compile"))
assert obs.compile_ok is True
assert "successful" in obs.tool_stdout.lower()
def test_run_sim_without_compile(self, environment, mac_reference_verilog):
environment.reset(task_id="mac_unit")
environment.step(VerirlAction(
action_type="write_file",
verilog_src=mac_reference_verilog
))
obs = environment.step(VerirlAction(action_type="run_sim"))
assert "ERROR" in obs.tool_stderr
def test_run_sim_after_compile(self, environment, mac_reference_verilog, requires_eda_tools):
environment.reset(task_id="mac_unit")
environment.step(VerirlAction(
action_type="write_file",
verilog_src=mac_reference_verilog
))
environment.step(VerirlAction(action_type="run_compile"))
obs = environment.step(VerirlAction(action_type="run_sim"))
assert obs.tests_total > 0
assert obs.tests_passed > 0
def test_write_file_resets_compile_ok(self, environment, mac_reference_verilog, requires_iverilog):
"""Rewriting code must clear compile_ok so stale state is never observed."""
environment.reset(task_id="mac_unit")
# Write good code and compile — compile_ok becomes True
environment.step(VerirlAction(action_type="write_file", verilog_src=mac_reference_verilog))
obs = environment.step(VerirlAction(action_type="run_compile"))
assert obs.compile_ok is True
# Overwrite with a different module — compile_ok must reset immediately
obs = environment.step(VerirlAction(
action_type="write_file",
verilog_src="module mac_unit (input clk); endmodule"
))
assert obs.compile_ok is False
def test_write_file_resets_sim_state(self, environment, mac_reference_verilog, requires_eda_tools):
"""Rewriting code must clear tests_passed/tests_total from any previous sim."""
environment.reset(task_id="mac_unit")
environment.step(VerirlAction(action_type="write_file", verilog_src=mac_reference_verilog))
environment.step(VerirlAction(action_type="run_compile"))
obs = environment.step(VerirlAction(action_type="run_sim"))
assert obs.tests_passed > 0
# Overwrite — sim state must be cleared
obs = environment.step(VerirlAction(
action_type="write_file",
verilog_src="module mac_unit (input clk); endmodule"
))
assert obs.tests_passed == 0
assert obs.tests_total == 0
class TestEnvironmentReward:
"""Test reward calculation."""
def test_reward_write_file(self, environment, mac_reference_verilog):
environment.reset(task_id="mac_unit")
obs = environment.step(VerirlAction(
action_type="write_file",
verilog_src=mac_reference_verilog
))
assert obs.reward > 0 # should get positive reward for writing
def test_reward_compile(self, environment, mac_reference_verilog, requires_iverilog):
environment.reset(task_id="mac_unit")
environment.step(VerirlAction(
action_type="write_file",
verilog_src=mac_reference_verilog
))
obs = environment.step(VerirlAction(action_type="run_compile"))
assert obs.reward > 0.02 # compile adds to reward
def test_reward_sim_passing(self, environment, mac_reference_verilog, requires_eda_tools):
environment.reset(task_id="mac_unit")
environment.step(VerirlAction(
action_type="write_file",
verilog_src=mac_reference_verilog
))
environment.step(VerirlAction(action_type="run_compile"))
obs = environment.step(VerirlAction(action_type="run_sim"))
assert obs.reward > 0.0 # Should have some reward from sim/tests
class TestEnvironmentDone:
"""Test episode termination."""
def test_submit_ends_episode(self, environment, mac_reference_verilog):
environment.reset(task_id="mac_unit")
environment.step(VerirlAction(
action_type="write_file",
verilog_src=mac_reference_verilog
))
environment.step(VerirlAction(action_type="run_compile"))
obs = environment.step(VerirlAction(action_type="submit"))
assert obs.done is True
assert obs.final_score is not None
def test_max_turns_expires(self, environment, mac_reference_verilog):
env = VerirlEnvironment(max_turns=2)
env.reset(task_id="mac_unit")
env.step(VerirlAction(action_type="write_file", verilog_src=mac_reference_verilog))
obs = env.step(VerirlAction(action_type="run_compile"))
assert obs.done is True # episode expires at max_turns
assert obs.final_score is not None
class TestTaskSelection:
"""Test task metadata and selection."""
def test_list_tasks(self, environment):
tasks = environment.list_tasks()
assert "mac_unit" in tasks
assert "axi_fifo" in tasks
assert "systolic_array" in tasks
def test_num_tasks(self, environment):
assert environment.num_tasks == 10
def test_invalid_task_id(self, environment):
with pytest.raises(ValueError):
environment.reset(task_id="invalid_task")