use agentvet::Validator;
use serde_json::json;
fn schema() -> serde_json::Value {
json!({
"type": "object",
"properties": {
"city": {"type": "string"},
"units": {"type": "string", "enum": ["c", "f"]},
"limit": {"type": "integer", "minimum": 1, "maximum": 100}
},
"required": ["city"],
"additionalProperties": false
})
}
#[test]
fn valid_args_pass() {
let v = Validator::from_schema(&schema()).unwrap();
v.validate(&json!({"city": "SFO", "units": "c"})).unwrap();
}
#[test]
fn missing_required_field_fails_with_hint() {
let v = Validator::from_schema(&schema()).unwrap();
let err = v.validate(&json!({"units": "c"})).unwrap_err();
assert!(!err.issues.is_empty());
let hint = err.for_llm();
assert!(hint.starts_with("Tool call rejected"));
assert!(hint.contains("city"));
}
#[test]
fn wrong_type_fails() {
let v = Validator::from_schema(&schema()).unwrap();
let err = v.validate(&json!({"city": 42})).unwrap_err();
let hint = err.for_llm();
assert!(hint.contains("city") || hint.contains("string") || hint.contains("type"));
}
#[test]
fn enum_violation_fails() {
let v = Validator::from_schema(&schema()).unwrap();
let err = v.validate(&json!({"city": "SFO", "units": "kelvin"})).unwrap_err();
let hint = err.for_llm();
assert!(hint.contains("units") || hint.contains("kelvin") || hint.contains("enum"));
}
#[test]
fn additional_properties_rejected() {
let v = Validator::from_schema(&schema()).unwrap();
let err = v.validate(&json!({"city": "SFO", "wat": "extra"})).unwrap_err();
assert!(!err.issues.is_empty());
}
#[test]
fn integer_bounds_enforced() {
let v = Validator::from_schema(&schema()).unwrap();
v.validate(&json!({"city": "SFO", "limit": 200})).unwrap_err();
v.validate(&json!({"city": "SFO", "limit": 0})).unwrap_err();
v.validate(&json!({"city": "SFO", "limit": 50})).unwrap();
}
#[test]
fn malformed_schema_errors_at_compile() {
let bad = json!({"type": 42});
let res = Validator::from_schema(&bad);
assert!(res.is_err());
}
#[test]
fn for_llm_format_is_useful() {
let v = Validator::from_schema(&schema()).unwrap();
let err = v
.validate(&json!({"units": "kelvin", "limit": 999}))
.unwrap_err();
let hint = err.for_llm();
let lines: Vec<&str> = hint.lines().collect();
assert_eq!(lines[0], "Tool call rejected. Fix and try again:");
assert!(lines.len() >= 2);
assert!(lines[1].starts_with(" - "));
}
#[test]
fn is_valid_short_circuits() {
let v = Validator::from_schema(&schema()).unwrap();
assert!(v.is_valid(&json!({"city": "SFO"})));
assert!(!v.is_valid(&json!({})));
}
#[test]
fn empty_object_when_required_field_missing() {
let v = Validator::from_schema(&schema()).unwrap();
let err = v.validate(&json!({})).unwrap_err();
assert!(err.for_llm().contains("city"));
}