Skip to main content

concinnity_dev/authoring/
check.rs

1// src/check.rs
2// Validate a world JSONL without producing blob files.
3//
4// Runs the validation front half of the build pipeline (load, expand, and
5// the semantic checks in `crate::check`) and reports the outcome. Used by
6// `cn test`, the FFI `cn_check_world` entry, and the infra agentic loop.
7
8/// Read `world_path`, run validation, and report results. Returns Ok if every
9/// asset passes; otherwise an error whose Display contains a human-readable
10/// summary of every failure (one per asset).
11pub fn check_at_path(world_path: &str) -> std::io::Result<()> {
12    let content = std::fs::read_to_string(world_path)?;
13    check_from_str(&content, world_path)
14}
15
16/// Run validation against an in-memory world JSONL string. `label` is the
17/// origin used in messages (typically the source path).
18pub fn check_from_str(content: &str, label: &str) -> std::io::Result<()> {
19    match concinnity_cook::prepare_world(
20        content,
21        crate::project::assets_dir().as_deref(),
22        crate::cook_platform(),
23    ) {
24        Ok(loaded) => {
25            println!("ok: {} asset(s) passed in {}", loaded.assets.len(), label);
26            Ok(())
27        }
28        Err(errors) => Err(concinnity_cook::check::report_validation_errors(&errors)),
29    }
30}
31
32#[cfg(test)]
33mod tests {
34    use super::*;
35
36    #[test]
37    fn check_from_str_accepts_a_valid_world() {
38        check_from_str(
39            "{\"name\":\"phys\",\"type\":\"PhysicsConfig\",\"args\":{}}\n",
40            "test",
41        )
42        .unwrap();
43    }
44
45    #[test]
46    fn check_from_str_rejects_an_unknown_type() {
47        let err = check_from_str(
48            "{\"name\":\"odd\",\"type\":\"NotARealAssetType\",\"args\":{}}\n",
49            "test",
50        )
51        .unwrap_err();
52        assert!(!err.to_string().is_empty());
53    }
54
55    #[test]
56    fn check_at_path_reports_a_missing_file() {
57        let dir = tempfile::tempdir().unwrap();
58        let path = dir.path().join("missing.jsonl");
59        assert!(check_at_path(path.to_str().unwrap()).is_err());
60    }
61
62    #[test]
63    fn check_at_path_accepts_a_valid_world_file() {
64        let dir = tempfile::tempdir().unwrap();
65        let path = dir.path().join("world.jsonl");
66        std::fs::write(
67            &path,
68            "{\"name\":\"phys\",\"type\":\"PhysicsConfig\",\"args\":{}}\n",
69        )
70        .unwrap();
71        check_at_path(path.to_str().unwrap()).unwrap();
72    }
73}