mecha10-behavior-runtime 0.1.25

Behavior tree runtime for Mecha10 - unified AI and logic composition system
Documentation
//! Integration tests for configuration loading and validation

use mecha10_behavior_runtime::{register_builtin_actions, validate_behavior_config, NodeRegistry};
use serde_json::json;

#[test]
fn test_validate_minimal_valid_behavior() {
    let mut registry = NodeRegistry::new();
    register_builtin_actions(&mut registry);

    let config = json!({
        "name": "test_behavior",
        "root": {
            "type": "sequence",
            "children": []
        }
    });

    let result = validate_behavior_config(&config, &registry).unwrap();
    assert!(result.valid, "Minimal behavior should be valid");
}

#[test]
fn test_validate_behavior_with_action_nodes() {
    let mut registry = NodeRegistry::new();
    register_builtin_actions(&mut registry);

    let config = json!({
        "name": "wander_behavior",
        "root": {
            "type": "sequence",
            "children": [
                {
                    "type": "wander",
                    "config": {
                        "topic": "/motor/cmd_vel",
                        "linear_speed": 0.5
                    }
                }
            ]
        }
    });

    let result = validate_behavior_config(&config, &registry).unwrap();
    assert!(result.valid, "Behavior with wander node should be valid");
    assert_eq!(result.errors.len(), 0, "Should have no errors");
}

#[test]
fn test_validate_missing_name_fails() {
    let registry = NodeRegistry::new();

    let config = json!({
        "root": {
            "type": "sequence",
            "children": []
        }
    });

    let result = validate_behavior_config(&config, &registry).unwrap();
    assert!(!result.valid, "Behavior without name should be invalid");
    assert!(
        result.errors.iter().any(|e| e.contains("name")),
        "Should have error about missing name"
    );
}

#[test]
fn test_validate_missing_root_fails() {
    let registry = NodeRegistry::new();

    let config = json!({
        "name": "test"
    });

    let result = validate_behavior_config(&config, &registry).unwrap();
    assert!(!result.valid, "Behavior without root should be invalid");
    assert!(
        result.errors.iter().any(|e| e.contains("root")),
        "Should have error about missing root"
    );
}

#[test]
fn test_validate_unknown_node_type_fails() {
    let registry = NodeRegistry::new();
    // Don't register any nodes

    let config = json!({
        "name": "test",
        "root": {
            "type": "unknown_custom_node",
            "config": {}
        }
    });

    let result = validate_behavior_config(&config, &registry).unwrap();
    assert!(!result.valid, "Behavior with unknown node should be invalid");
    assert!(
        result.errors.iter().any(|e| e.contains("unknown_custom_node")),
        "Should have error about unknown node type"
    );
}

#[test]
fn test_validate_composition_nodes_allowed() {
    let registry = NodeRegistry::new();

    let config = json!({
        "name": "test",
        "root": {
            "type": "sequence",
            "children": [
                {
                    "type": "selector",
                    "children": [
                        {
                            "type": "parallel",
                            "children": []
                        }
                    ]
                }
            ]
        }
    });

    let result = validate_behavior_config(&config, &registry).unwrap();
    assert!(result.valid, "Composition nodes should not require registration");
}

#[test]
fn test_validate_empty_children_warns() {
    let registry = NodeRegistry::new();

    let config = json!({
        "name": "test",
        "root": {
            "type": "sequence",
            "children": []
        }
    });

    let result = validate_behavior_config(&config, &registry).unwrap();
    assert!(result.valid, "Empty children should be valid");
    assert!(!result.warnings.is_empty(), "Should have warning about empty children");
}

#[test]
fn test_validate_missing_schema_warns() {
    let registry = NodeRegistry::new();

    let config = json!({
        "name": "test",
        "root": {
            "type": "sequence",
            "children": []
        }
    });

    let result = validate_behavior_config(&config, &registry).unwrap();
    assert!(
        result.warnings.iter().any(|w| w.contains("$schema")),
        "Should warn about missing schema reference"
    );
}