mecha10-behavior-patterns 0.1.23

Common behavior patterns for Mecha10 - subsumption, ensemble, and more
Documentation
// Tests for mecha10_behavior_patterns::subsumption

use async_trait::async_trait;
use mecha10_behavior_patterns::*;
use mecha10_behavior_runtime::prelude::*;

#[derive(Debug)]
struct MockBehavior {
    status: NodeStatus,
    tick_count: usize,
}

impl MockBehavior {
    fn new(status: NodeStatus) -> Self {
        Self { status, tick_count: 0 }
    }
}

#[async_trait]
impl BehaviorNode for MockBehavior {
    async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
        self.tick_count += 1;
        Ok(self.status)
    }
}

#[tokio::test]
#[ignore = "Requires Redis infrastructure"]
async fn test_subsumption_highest_priority_wins() {
    let ctx = Context::new("test").await.unwrap();

    let mut subsumption = SubsumptionNode::new()
        .add_layer(10, Box::new(MockBehavior::new(NodeStatus::Success))) // High priority - succeeds
        .add_layer(5, Box::new(MockBehavior::new(NodeStatus::Running))) // Should not execute
        .add_layer(1, Box::new(MockBehavior::new(NodeStatus::Running))); // Should not execute

    let status = subsumption.tick(&ctx).await.unwrap();
    assert_eq!(status, NodeStatus::Success);
}

#[tokio::test]
#[ignore = "Requires Redis infrastructure"]
async fn test_subsumption_fallback_to_lower_priority() {
    let ctx = Context::new("test").await.unwrap();

    let mut subsumption = SubsumptionNode::new()
        .add_layer(10, Box::new(MockBehavior::new(NodeStatus::Failure))) // Fails
        .add_layer(5, Box::new(MockBehavior::new(NodeStatus::Success))) // This should execute
        .add_layer(1, Box::new(MockBehavior::new(NodeStatus::Running))); // Should not execute

    let status = subsumption.tick(&ctx).await.unwrap();
    assert_eq!(status, NodeStatus::Success);
}

#[tokio::test]
#[ignore = "Requires Redis infrastructure"]
async fn test_subsumption_all_fail() {
    let ctx = Context::new("test").await.unwrap();

    let mut subsumption = SubsumptionNode::new()
        .add_layer(10, Box::new(MockBehavior::new(NodeStatus::Failure)))
        .add_layer(5, Box::new(MockBehavior::new(NodeStatus::Failure)))
        .add_layer(1, Box::new(MockBehavior::new(NodeStatus::Failure)));

    let status = subsumption.tick(&ctx).await.unwrap();
    assert_eq!(status, NodeStatus::Failure);
}

#[test]
fn test_layer_sorting() {
    let subsumption = SubsumptionNode::new()
        .add_layer(5, Box::new(MockBehavior::new(NodeStatus::Success)))
        .add_layer(10, Box::new(MockBehavior::new(NodeStatus::Success)))
        .add_layer(1, Box::new(MockBehavior::new(NodeStatus::Success)));

    // Verify layers are sorted by priority descending
    assert_eq!(subsumption.layers[0].priority, 10);
    assert_eq!(subsumption.layers[1].priority, 5);
    assert_eq!(subsumption.layers[2].priority, 1);
}