Skip to content

Commit bbe1222

Browse files
authored
Create test_runtime_config.py
1 parent 4e85e0a commit bbe1222

1 file changed

Lines changed: 131 additions & 0 deletions

File tree

tests/test_runtime_config.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
"""
2+
IX-HapticSight — Tests for runtime configuration loading and wiring.
3+
4+
These tests validate the new runtime configuration bundle against the
5+
repository's real YAML files and a few targeted invalid-config cases.
6+
"""
7+
8+
import os
9+
import sys
10+
from pathlib import Path
11+
from tempfile import TemporaryDirectory
12+
13+
# Make both `ohip` and `ohip_runtime` importable without packaging
14+
sys.path.insert(0, os.path.abspath("src"))
15+
16+
import yaml # noqa: E402
17+
18+
from ohip.consent_manager import ConsentManager # noqa: E402
19+
from ohip.contact_planner import ContactPlanner # noqa: E402
20+
from ohip.safety_gate import SafetyGate # noqa: E402
21+
from ohip_runtime.config import ( # noqa: E402
22+
RuntimeComponentBundle,
23+
RuntimeConfigBundle,
24+
)
25+
26+
27+
def repo_root() -> Path:
28+
return Path(__file__).resolve().parents[1]
29+
30+
31+
def test_runtime_config_bundle_loads_real_repo_files():
32+
bundle = RuntimeConfigBundle.from_repo_root(repo_root())
33+
34+
assert bundle.force_limits_path.name == "force_limits.yaml"
35+
assert bundle.culture_profiles_path.name == "culture_profiles.yaml"
36+
37+
assert "profiles" in bundle.force_limits
38+
assert "profiles" in bundle.culture_profiles
39+
40+
assert "human_soft_touch_v1" in bundle.force_profile_names
41+
assert "default" in bundle.culture_profile_names
42+
assert "support_request" in bundle.phrase_bank
43+
44+
assert bundle.default_force_profile_name() == "human_soft_touch_v1"
45+
assert bundle.bound_force_profile_for_culture("default") == "human_soft_touch_v1"
46+
assert bundle.bound_force_profile_for_culture("us") == "human_soft_touch_v1"
47+
48+
49+
def test_runtime_config_builds_runtime_components_from_real_repo_files():
50+
bundle = RuntimeConfigBundle.from_repo_root(repo_root())
51+
52+
components = bundle.build_runtime_components(
53+
culture_profile_name="default",
54+
institutional_policy_enabled=False,
55+
)
56+
57+
assert isinstance(components, RuntimeComponentBundle)
58+
assert isinstance(components.consent_manager, ConsentManager)
59+
assert isinstance(components.contact_planner, ContactPlanner)
60+
assert isinstance(components.safety_gate, SafetyGate)
61+
assert components.safety_gate._active_profile == "human_soft_touch_v1"
62+
63+
64+
def test_get_culture_profile_unknown_raises():
65+
bundle = RuntimeConfigBundle.from_repo_root(repo_root())
66+
67+
try:
68+
bundle.get_culture_profile("missing_profile")
69+
raised = False
70+
except KeyError:
71+
raised = True
72+
73+
assert raised is True
74+
75+
76+
def test_invalid_force_profile_binding_is_rejected():
77+
root = repo_root()
78+
with TemporaryDirectory() as tmpdir:
79+
tmp = Path(tmpdir)
80+
81+
force_data = yaml.safe_load((root / "configs" / "force_limits.yaml").read_text(encoding="utf-8"))
82+
culture_data = yaml.safe_load((root / "configs" / "culture_profiles.yaml").read_text(encoding="utf-8"))
83+
84+
culture_data["profiles"]["default"]["bindings"]["force_profile"] = "does_not_exist"
85+
86+
force_path = tmp / "force_limits.yaml"
87+
culture_path = tmp / "culture_profiles.yaml"
88+
89+
force_path.write_text(yaml.safe_dump(force_data, sort_keys=False), encoding="utf-8")
90+
culture_path.write_text(yaml.safe_dump(culture_data, sort_keys=False), encoding="utf-8")
91+
92+
try:
93+
RuntimeConfigBundle.from_files(
94+
force_limits_path=force_path,
95+
culture_profiles_path=culture_path,
96+
)
97+
raised = False
98+
except ValueError as exc:
99+
raised = True
100+
assert "unknown force profile" in str(exc)
101+
102+
assert raised is True
103+
104+
105+
def test_missing_social_touch_profile_is_rejected():
106+
root = repo_root()
107+
with TemporaryDirectory() as tmpdir:
108+
tmp = Path(tmpdir)
109+
110+
force_data = yaml.safe_load((root / "configs" / "force_limits.yaml").read_text(encoding="utf-8"))
111+
culture_data = yaml.safe_load((root / "configs" / "culture_profiles.yaml").read_text(encoding="utf-8"))
112+
113+
force_data["defaults"].pop("social_touch_profile", None)
114+
115+
force_path = tmp / "force_limits.yaml"
116+
culture_path = tmp / "culture_profiles.yaml"
117+
118+
force_path.write_text(yaml.safe_dump(force_data, sort_keys=False), encoding="utf-8")
119+
culture_path.write_text(yaml.safe_dump(culture_data, sort_keys=False), encoding="utf-8")
120+
121+
try:
122+
RuntimeConfigBundle.from_files(
123+
force_limits_path=force_path,
124+
culture_profiles_path=culture_path,
125+
)
126+
raised = False
127+
except ValueError as exc:
128+
raised = True
129+
assert "social_touch_profile" in str(exc)
130+
131+
assert raised is True

0 commit comments

Comments
 (0)