use super::*;
use tempfile::TempDir;
fn tool(name: &str) -> Tool {
Tool {
name: name.to_owned(),
description: format!("what {name} does"),
input_schema: json!({"type": "object", "properties": {"cmd": {"type": "string"}}}),
subject_cwd: false,
}
}
fn entry(client: &str, name: &str) -> Entry {
Entry {
client: client.to_owned(),
tool: tool(name),
}
}
#[test]
fn a_presented_name_carries_the_client_that_advertises_it() {
assert_eq!(entry("laptop", "Bash").presented(), "laptop_Bash");
assert_eq!(entry("desk", "Bash").presented(), "desk_Bash");
}
#[test]
fn a_callable_name_is_ascii_word_characters_and_bounded() {
assert!(callable("laptop_Bash"));
assert!(callable("a-b_C9"));
assert!(callable(&"x".repeat(64)));
assert!(!callable(""));
assert!(!callable(&"x".repeat(65)));
assert!(!callable("laptop.local_Bash"));
}
#[test]
fn the_document_is_addressed_by_workspace_and_agent() {
let root = Path::new("/home/u/state/yog");
assert_eq!(
path(root, "home", "dulcet-mongoose").expect("a usable address"),
root.join(LOADED).join("home").join("dulcet-mongoose.json")
);
}
#[test]
fn a_name_that_could_address_the_filesystem_has_no_document() {
let root = Path::new("/home/u/state/yog");
assert!(path(root, "../escape", "a").is_none());
assert!(path(root, "home", "..").is_none());
assert!(read(root, "home", "..").is_empty());
}
#[test]
fn a_set_survives_its_one_spelling() {
let set = vec![entry("laptop", "Bash"), entry("desk", "Read")];
let wire = encode(&set);
assert_eq!(decode(&wire).expect("decoded"), set);
assert_eq!(
wire[0]["tool"],
crate::registry::tools::one(&set[0].tool),
"the element is the registry's spelling, not a second one"
);
}
#[test]
fn a_malformed_document_refuses_naming_what_is_wrong() {
assert!(
decode(&json!({}))
.expect_err("not an array")
.contains("array")
);
assert!(
decode(&json!([7]))
.expect_err("not an object")
.contains("object")
);
assert!(
decode(&json!([{"tool": {"name": "B", "description": "d", "input_schema": {}}}]))
.expect_err("no client")
.contains("client")
);
assert!(
decode(&json!([{"client": "laptop"}]))
.expect_err("no tool")
.contains("tool")
);
assert!(
decode(&json!([{"client": "laptop", "tool": {"name": "B"}}]))
.expect_err("bad tool")
.contains("description")
);
}
#[test]
fn an_unreadable_document_reads_as_nothing_loaded() {
let root = TempDir::new().expect("tmp");
assert!(read(root.path(), "home", "agent").is_empty());
let file = path(root.path(), "home", "agent").expect("address");
std::fs::create_dir_all(file.parent().expect("parent")).expect("mkdir");
std::fs::write(&file, b"{").expect("write");
assert!(read(root.path(), "home", "agent").is_empty());
std::fs::write(&file, b"{\"not\": \"an array\"}").expect("write");
assert!(read(root.path(), "home", "agent").is_empty());
}
#[test]
fn a_load_is_durable() {
let root = TempDir::new().expect("tmp");
let one = entry("laptop", "Bash");
let all = add(root.path(), "home", "agent", std::slice::from_ref(&one)).expect("added");
assert_eq!(all, vec![one.clone()]);
assert_eq!(read(root.path(), "home", "agent"), vec![one]);
}
#[test]
fn a_second_load_unions_and_a_reload_refreshes() {
let root = TempDir::new().expect("tmp");
add(
root.path(),
"home",
"agent",
&[entry("laptop", "Bash"), entry("desk", "Read")],
)
.expect("added");
let mut refreshed = entry("laptop", "Bash");
refreshed.tool.description = "a newer sentence".to_owned();
let all = add(
root.path(),
"home",
"agent",
&[refreshed.clone(), entry("laptop", "Write")],
)
.expect("added");
assert_eq!(
all.iter().map(Entry::presented).collect::<Vec<_>>(),
vec!["desk_Read", "laptop_Bash", "laptop_Write"],
"unioned by presented name, sorted"
);
assert_eq!(all[1], refreshed, "the later definition won");
}
#[test]
fn a_load_at_an_unusable_address_refuses() {
let root = TempDir::new().expect("tmp");
let e = add(root.path(), "..", "agent", &[entry("laptop", "Bash")]).expect_err("refused");
assert!(e.to_string().contains("unusable address"), "{e}");
}