use mecha10_behavior_runtime::{BehaviorConfig, CompositionConfig, ParallelPolicyConfig};
use std::collections::HashMap;
#[test]
fn test_parse_simple_sequence() {
let json = r#"{
"name": "test",
"root": {
"type": "sequence",
"children": []
}
}"#;
let config = BehaviorConfig::from_json(json).unwrap();
assert_eq!(config.name, "test");
match config.root {
CompositionConfig::Sequence { children, .. } => {
assert_eq!(children.len(), 0);
}
_ => panic!("Expected sequence"),
}
}
#[test]
fn test_parse_node_with_config_ref() {
let json = r#"{
"name": "test",
"root": {
"type": "node",
"node": "my_behavior",
"config_ref": "my_config"
},
"configs": {
"my_config": {
"speed": 1.5
}
}
}"#;
let config = BehaviorConfig::from_json(json).unwrap();
match &config.root {
CompositionConfig::Node { node, config_ref, .. } => {
assert_eq!(node, "my_behavior");
assert_eq!(config_ref, &Some("my_config".to_string()));
}
_ => panic!("Expected node"),
}
let node_config = config.get_config("my_config").unwrap();
assert_eq!(node_config["speed"], 1.5);
}
#[test]
fn test_parse_parallel_with_policy() {
let json = r#"{
"name": "test",
"root": {
"type": "parallel",
"policy": "require_one",
"children": []
}
}"#;
let config = BehaviorConfig::from_json(json).unwrap();
match config.root {
CompositionConfig::Parallel { policy, .. } => {
assert!(matches!(policy, ParallelPolicyConfig::RequireOne));
}
_ => panic!("Expected parallel"),
}
}
#[test]
fn test_parse_inverter_decorator() {
let json = r#"{
"name": "test",
"root": {
"type": "inverter",
"child": { "type": "node", "node": "my_behavior" }
}
}"#;
let config = BehaviorConfig::from_json(json).unwrap();
match config.root {
CompositionConfig::Inverter { child, .. } => {
assert!(matches!(*child, CompositionConfig::Node { .. }));
}
_ => panic!("Expected inverter"),
}
}
#[test]
fn test_parse_repeat_decorator_with_count() {
let json = r#"{
"name": "test",
"root": {
"type": "repeat",
"count": 3,
"child": { "type": "node", "node": "my_behavior" }
}
}"#;
let config = BehaviorConfig::from_json(json).unwrap();
match config.root {
CompositionConfig::Repeat { count, .. } => {
assert_eq!(count, Some(3));
}
_ => panic!("Expected repeat"),
}
}
#[test]
fn test_parse_repeat_decorator_without_count_defaults_to_infinite() {
let json = r#"{
"name": "test",
"root": {
"type": "repeat",
"child": { "type": "node", "node": "my_behavior" }
}
}"#;
let config = BehaviorConfig::from_json(json).unwrap();
match config.root {
CompositionConfig::Repeat { count, .. } => {
assert_eq!(count, None);
}
_ => panic!("Expected repeat"),
}
}
#[test]
fn test_parse_retry_decorator() {
let json = r#"{
"name": "test",
"root": {
"type": "retry",
"max_attempts": 3,
"child": { "type": "node", "node": "my_behavior" }
}
}"#;
let config = BehaviorConfig::from_json(json).unwrap();
match config.root {
CompositionConfig::Retry { max_attempts, .. } => {
assert_eq!(max_attempts, 3);
}
_ => panic!("Expected retry"),
}
}
#[test]
fn test_parse_timeout_decorator() {
let json = r#"{
"name": "test",
"root": {
"type": "timeout",
"timeout_secs": 30.0,
"child": { "type": "node", "node": "my_behavior" }
}
}"#;
let config = BehaviorConfig::from_json(json).unwrap();
match config.root {
CompositionConfig::Timeout { timeout_secs, .. } => {
assert_eq!(timeout_secs, 30.0);
}
_ => panic!("Expected timeout"),
}
}
#[test]
fn test_parse_force_success_and_force_failure_decorators() {
let json = r#"{
"name": "test",
"root": {
"type": "sequence",
"children": [
{ "type": "force_success", "child": { "type": "node", "node": "a" } },
{ "type": "force_failure", "child": { "type": "node", "node": "b" } }
]
}
}"#;
let config = BehaviorConfig::from_json(json).unwrap();
match config.root {
CompositionConfig::Sequence { children, .. } => {
assert!(matches!(children[0], CompositionConfig::ForceSuccess { .. }));
assert!(matches!(children[1], CompositionConfig::ForceFailure { .. }));
}
_ => panic!("Expected sequence"),
}
}
#[test]
fn test_generate_schema() {
let schema = BehaviorConfig::generate_schema().unwrap();
assert!(schema.contains("BehaviorConfig"));
assert!(schema.contains("CompositionConfig"));
}
#[test]
fn test_roundtrip() {
let config = BehaviorConfig {
schema: None,
name: "test".to_string(),
description: Some("Test behavior".to_string()),
root: CompositionConfig::Sequence {
children: vec![],
name: None,
},
configs: HashMap::new(),
requires_capabilities: Vec::new(),
};
let json = config.to_json().unwrap();
let parsed = BehaviorConfig::from_json(&json).unwrap();
assert_eq!(parsed.name, config.name);
assert_eq!(parsed.description, config.description);
}