Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
"""Regression tests for `config set` value coercion + key validation (round-3 CFG).
|
||||
|
||||
Covers:
|
||||
- CFG-02: negative / whitespace-padded numerics coerce to int/float on
|
||||
numeric-typed keys (old code used str.isdigit() and stored strings).
|
||||
- CFG-05: null/none/~ coerce to None so a nullable field can be cleared.
|
||||
- CFG-04: malformed dotted keys with empty segments are rejected.
|
||||
- Guard: string-typed enum keys (approvals.mode) are NOT coerced.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli import config as cfg
|
||||
|
||||
|
||||
def _read(tmp_path, *path):
|
||||
"""Read a nested value straight from the on-disk config.yaml."""
|
||||
import yaml
|
||||
data = yaml.safe_load((tmp_path / "config.yaml").read_text()) or {}
|
||||
node = data
|
||||
for seg in path:
|
||||
node = node[seg]
|
||||
return node
|
||||
|
||||
|
||||
class TestNumericCoercion:
|
||||
def test_negative_int(self, tmp_path, monkeypatch):
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
cfg.set_config_value("agent.max_turns", "-5")
|
||||
v = _read(tmp_path, "agent", "max_turns")
|
||||
assert v == -5 and isinstance(v, int)
|
||||
|
||||
def test_whitespace_padded_int(self, tmp_path, monkeypatch):
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
cfg.set_config_value("agent.max_turns", " 42 ")
|
||||
v = _read(tmp_path, "agent", "max_turns")
|
||||
assert v == 42 and isinstance(v, int)
|
||||
|
||||
def test_negative_float(self, tmp_path, monkeypatch):
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
cfg.set_config_value("agent.max_turns", "-2.5")
|
||||
v = _read(tmp_path, "agent", "max_turns")
|
||||
assert v == -2.5 and isinstance(v, float)
|
||||
|
||||
def test_lossy_decimal_identifier_stays_string(self, tmp_path, monkeypatch):
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
client_id = "123456789012.98765432109876"
|
||||
|
||||
cfg.set_config_value("mcp_servers.example.oauth.client_id", client_id)
|
||||
|
||||
saved = _read(
|
||||
tmp_path, "mcp_servers", "example", "oauth", "client_id"
|
||||
)
|
||||
assert saved == client_id
|
||||
assert isinstance(saved, str)
|
||||
|
||||
|
||||
class TestNullCoercion:
|
||||
@pytest.mark.parametrize("token", ["null", "none", "None", "~"])
|
||||
def test_null_tokens_coerce_to_none(self, tmp_path, monkeypatch, token):
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
cfg.set_config_value("agent.run_budget_seconds", token)
|
||||
assert _read(tmp_path, "agent", "run_budget_seconds") is None
|
||||
|
||||
|
||||
class TestMalformedKey:
|
||||
@pytest.mark.parametrize("bad", ["agent.", ".agent", "agent..max_turns", " "])
|
||||
def test_empty_segment_rejected(self, tmp_path, monkeypatch, bad):
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
with pytest.raises(SystemExit) as exc:
|
||||
cfg.set_config_value(bad, "5")
|
||||
assert exc.value.code == 1
|
||||
|
||||
|
||||
class TestStringTypedGuardPreserved:
|
||||
def test_enum_off_stays_string(self, tmp_path, monkeypatch):
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
cfg.set_config_value("approvals.mode", "off")
|
||||
v = _read(tmp_path, "approvals", "mode")
|
||||
assert v == "off" and isinstance(v, str) # not bool False
|
||||
Reference in New Issue
Block a user