use super::{Tool, encode, of_one, one, validate};
use serde_json::{Value, json};
fn bash() -> Tool {
Tool {
name: "Bash".to_owned(),
description: "run a command in a shell".to_owned(),
input_schema: json!({"type": "object",
"properties": {"command": {"type": "string"}},
"required": ["command"]}),
}
}
#[test]
fn an_element_is_three_facts_and_the_schema_is_untouched() {
let said = one(&bash());
let o = said.as_object().expect("an object");
assert_eq!(o.len(), 3, "nothing else rides along: {said}");
assert_eq!(o["input_schema"], bash().input_schema);
assert_eq!(of_one(&said), Ok(bash()));
}
#[test]
fn a_set_encodes_as_its_array() {
let other = Tool {
name: "Read".to_owned(),
description: "read a file".to_owned(),
input_schema: json!({"type": "object"}),
};
let said = encode(&[bash(), other.clone()]);
let rows = said.as_array().expect("an array");
assert_eq!(rows.len(), 2);
assert_eq!(of_one(&rows[0]), Ok(bash()));
assert_eq!(of_one(&rows[1]), Ok(other));
}
#[test]
fn an_element_that_is_missing_something_refuses_by_key() {
assert_eq!(
of_one(&json!("Bash")),
Err("tool: not a JSON object".to_owned())
);
assert_eq!(
of_one(&json!({"description": "d", "input_schema": {}})),
Err("tool: missing field \"name\"".to_owned())
);
assert_eq!(
of_one(&json!({"name": "Bash", "input_schema": {}})),
Err("tool: missing field \"description\"".to_owned())
);
assert_eq!(
of_one(&json!({"name": "Bash", "description": "d"})),
Err("tool: missing field \"input_schema\"".to_owned())
);
assert_eq!(
of_one(&json!({"name": 7, "description": "d", "input_schema": {}})),
Err("tool: field \"name\" is not a string".to_owned())
);
}
#[test]
fn a_schema_is_carried_whatever_it_is() {
let odd = json!({"name": "Bash", "description": "d", "input_schema": "not a schema"});
assert_eq!(
of_one(&odd).map(|t| t.input_schema),
Ok(Value::String("not a schema".to_owned()))
);
}
#[test]
fn a_name_that_is_not_a_single_path_component_is_refused() {
for unusable in ["", ".", "..", "tools/Bash", "tools\\Bash", "Ba\0sh"] {
let named = Tool {
name: unusable.to_owned(),
..bash()
};
let refusal = validate(&[named]).expect_err("refused");
assert!(refusal.starts_with("unusable tool name"), "{refusal}");
}
}
#[test]
fn one_name_twice_in_one_set_declines_naming_it() {
let refusal = validate(&[bash(), bash()]).expect_err("refused");
assert_eq!(refusal, "duplicate tool name \"Bash\"");
}
#[test]
fn an_addressable_set_passes_and_so_does_an_empty_one() {
assert_eq!(validate(&[bash()]), Ok(()));
assert_eq!(validate(&[]), Ok(()));
}