use anyhow::Result;
use std::path::PathBuf;
use toolpath::v1::Document;
use crate::io::read_document_auto;
pub fn run(input: PathBuf) -> Result<()> {
match read_document_auto(&input) {
Ok(doc) => {
println!("Valid: {}", describe(&doc));
Ok(())
}
Err(e) => Err(anyhow::anyhow!("Invalid: {}", e)),
}
}
fn describe(doc: &Document) -> String {
match doc {
Document::Graph(g) => format!("Graph (id: {})", g.graph.id),
Document::Path(p) => format!("Path (id: {}, {} steps)", p.path.id, p.steps.len()),
Document::Step(s) => format!("Step (id: {})", s.step.id),
}
}
#[cfg(test)]
fn validate_content(content: &str) -> Result<()> {
match Document::from_json(content) {
Ok(doc) => {
println!("Valid: {}", describe(&doc));
Ok(())
}
Err(e) => Err(anyhow::anyhow!("Invalid: {}", e)),
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::Write;
#[test]
fn test_validate_valid_step() {
let json = r#"{"Step":{"step":{"id":"s1","actor":"human:alex","timestamp":"2026-01-01T00:00:00Z"},"change":{}}}"#;
assert!(validate_content(json).is_ok());
}
#[test]
fn test_validate_valid_path() {
let json = r#"{"Path":{"path":{"id":"p1","head":"s1"},"steps":[]}}"#;
assert!(validate_content(json).is_ok());
}
#[test]
fn test_validate_valid_graph() {
let json = r#"{"Graph":{"graph":{"id":"g1"},"paths":[]}}"#;
assert!(validate_content(json).is_ok());
}
#[test]
fn test_validate_invalid_json() {
assert!(validate_content("not json").is_err());
}
#[test]
fn test_validate_invalid_structure() {
assert!(validate_content(r#"{"Unknown":{}}"#).is_err());
}
#[test]
fn test_run_with_temp_file() {
let mut f = tempfile::NamedTempFile::new().unwrap();
write!(f, r#"{{"Step":{{"step":{{"id":"s1","actor":"human:alex","timestamp":"2026-01-01T00:00:00Z"}},"change":{{}}}}}}"#).unwrap();
f.flush().unwrap();
assert!(run(f.path().to_path_buf()).is_ok());
}
#[test]
fn test_run_nonexistent_file() {
assert!(run(PathBuf::from("/nonexistent/file.json")).is_err());
}
}