Spaces:
Sleeping
Sleeping
| """Unit tests for the robust parser contract.""" | |
| import pytest | |
| from utils.parser import parse_llm_action | |
| from utils.schemas import ParsedAction | |
| from utils.constants import PARSER_DEFAULT_U, PARSER_DEFAULT_F, INVALID_ACTION_PENALTY | |
| def test_valid_json(): | |
| text = '{"U_target": 0.3, "F_target": 0.7}' | |
| result = parse_llm_action(text) | |
| assert result.u_target == 0.3 | |
| assert result.f_target == 0.7 | |
| assert result.source == "json" | |
| assert result.invalid_output is False | |
| assert result.penalty_applied == 0.0 | |
| assert result.parse_error is None | |
| def test_json_missing_keys(): | |
| text = '{"U_target": 0.3}' | |
| result = parse_llm_action(text) | |
| assert result.source == "default" | |
| assert result.invalid_output is True | |
| assert result.penalty_applied == -INVALID_ACTION_PENALTY | |
| assert result.parse_error is not None and "missing required keys" in result.parse_error | |
| assert result.u_target == PARSER_DEFAULT_U | |
| assert result.f_target == PARSER_DEFAULT_F | |
| def test_anchored_extraction(): | |
| # Quoted | |
| text1 = 'Here is the action: "U_target":0.3 and later "F_target":0.7.' | |
| result1 = parse_llm_action(text1) | |
| assert result1.source == "fallback" | |
| assert result1.invalid_output is True | |
| assert result1.u_target == 0.3 | |
| assert result1.f_target == 0.7 | |
| # Unquoted with equals | |
| text2 = 'U_target = 0.2, F_target = 0.8' | |
| result2 = parse_llm_action(text2) | |
| assert result2.source == "fallback" | |
| assert result2.invalid_output is True | |
| assert result2.u_target == 0.2 | |
| assert result2.f_target == 0.8 | |
| # Unquoted with space and case insensitivity | |
| text3 = 'u_target 0.1 f_target 0.9' | |
| result3 = parse_llm_action(text3) | |
| assert result3.source == "fallback" | |
| assert result3.invalid_output is True | |
| assert result3.u_target == 0.1 | |
| assert result3.f_target == 0.9 | |
| def test_pair_format(): | |
| # Whitespace | |
| text1 = ' 0.3 0.7 ' | |
| result1 = parse_llm_action(text1) | |
| assert result1.source == "fallback" | |
| assert result1.invalid_output is False | |
| assert result1.penalty_applied == 0.0 | |
| assert result1.u_target == 0.3 | |
| assert result1.f_target == 0.7 | |
| # Comma separation | |
| text2 = '0.3,0.7' | |
| result2 = parse_llm_action(text2) | |
| assert result2.source == "fallback" | |
| assert result2.invalid_output is False | |
| assert result2.u_target == 0.3 | |
| assert result2.f_target == 0.7 | |
| # Semicolon | |
| text3 = '0.3; 0.7' | |
| result3 = parse_llm_action(text3) | |
| assert result3.source == "fallback" | |
| assert result3.invalid_output is False | |
| assert result3.u_target == 0.3 | |
| assert result3.f_target == 0.7 | |
| def test_out_of_range_clamping(): | |
| text = '{"U_target": -1.0, "F_target": 2.0}' | |
| result = parse_llm_action(text) | |
| assert result.source == "json" | |
| assert result.u_target == 0.0 | |
| assert result.f_target == 1.0 | |
| def test_empty_string_fallback(): | |
| text = '' | |
| result = parse_llm_action(text, previous_valid_action=None) | |
| assert result.source == "default" | |
| assert result.invalid_output is True | |
| assert result.penalty_applied == -INVALID_ACTION_PENALTY | |
| assert result.u_target == PARSER_DEFAULT_U | |
| assert result.f_target == PARSER_DEFAULT_F | |
| def test_previous_valid_action(): | |
| text = 'invalid nonsens' | |
| prev_action = {"U_target": 0.45, "F_target": 0.55} | |
| result = parse_llm_action(text, previous_valid_action=prev_action) | |
| assert result.source == "previous_valid" | |
| assert result.invalid_output is True | |
| assert result.penalty_applied == -INVALID_ACTION_PENALTY | |
| assert result.u_target == 0.45 | |
| assert result.f_target == 0.55 | |