disaster-triage-command / tests /test_validation.py
Keerthisujana's picture
Deploy Disaster Triage Command
1676aa7
Raw
History Blame Contribute Delete
3.45 kB
import sys, os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from core.validation import (
safe_parse_llm_json, ValidationError, clamp, coerce_int, coerce_float,
coerce_need_types, validate_image_file, validate_report_text,
)
def test_parses_clean_json():
data = safe_parse_llm_json('{"people_affected": 10, "urgency": 5, "need_types": ["medical"]}',
required_keys=["people_affected", "urgency"])
assert data["people_affected"] == 10
print("PASS: clean JSON parses correctly")
def test_parses_json_wrapped_in_prose_and_fences():
raw = 'Sure, here is the JSON:\n```json\n{"people_affected": 7, "urgency": 3}\n```\nLet me know if you need more.'
data = safe_parse_llm_json(raw, required_keys=["people_affected", "urgency"])
assert data["people_affected"] == 7
print("PASS: JSON wrapped in markdown fences + prose is correctly extracted")
def test_raises_on_missing_required_keys():
try:
safe_parse_llm_json('{"people_affected": 5}', required_keys=["people_affected", "urgency"])
assert False, "should have raised"
except ValidationError:
print("PASS: missing required key raises ValidationError")
def test_raises_on_empty_output():
try:
safe_parse_llm_json("", required_keys=["x"])
assert False, "should have raised"
except ValidationError:
print("PASS: empty model output raises ValidationError")
def test_raises_on_garbage_output():
try:
safe_parse_llm_json("I cannot help with that request.", required_keys=["x"])
assert False, "should have raised"
except ValidationError:
print("PASS: non-JSON garbage output raises ValidationError")
def test_coerce_int_clamps_and_defaults():
assert coerce_int("12", lo=0, hi=10) == 10
assert coerce_int(-5, lo=0, hi=10) == 0
assert coerce_int("not a number", default=3) == 3
print("PASS: coerce_int clamps and falls back on garbage")
def test_coerce_float_clamps():
assert coerce_float(99, lo=0, hi=10) == 10
assert coerce_float(None, default=5.0) == 5.0
print("PASS: coerce_float clamps and falls back on garbage")
def test_coerce_need_types_filters_unknown_values():
result = coerce_need_types(["medical", "teleportation", "rescue", "medical"])
assert result == ["medical", "rescue"], f"got {result}"
print("PASS: coerce_need_types filters unknown values and dedupes")
def test_validate_report_text_handles_empty_and_long():
text, warning = validate_report_text("")
assert text == "" and warning
print("PASS: empty report text flagged with warning")
long_text = "x" * 5000
text, warning = validate_report_text(long_text, max_chars=4000)
assert len(text) == 4000 and "truncated" in warning
print("PASS: overlong report text truncated with warning")
def test_validate_image_file_missing():
is_valid, err = validate_image_file("/nonexistent/path/image.png")
assert not is_valid and err
print("PASS: missing image file correctly flagged invalid")
def test_clamp():
assert clamp(15, 0, 10) == 10
assert clamp(-5, 0, 10) == 0
assert clamp(5, 0, 10) == 5
print("PASS: clamp works at both bounds and in range")
if __name__ == "__main__":
tests = [v for k, v in list(globals().items()) if k.startswith("test_")]
for t in tests:
t()
print(f"\n{len(tests)}/{len(tests)} validation tests passed.")