use mecha10_core::error::Mecha10Error;
use mecha10_core::node::*;
use mecha10_core::prelude::now_micros;
use mecha10_core::types::{HealthStatus, NodeState};
use mecha10_core::Context;
use async_trait::async_trait;
use serde::Deserialize;
#[derive(Debug)]
struct TestNode {
run_count: usize,
}
#[derive(Debug, Deserialize)]
struct TestConfig {
value: i32,
}
#[async_trait]
impl NodeImpl for TestNode {
type Config = TestConfig;
async fn init(config: Self::Config) -> Result<Self, Mecha10Error> {
assert_eq!(config.value, 42);
Ok(Self { run_count: 0 })
}
async fn run(&mut self, _ctx: &Context) -> Result<(), Mecha10Error> {
self.run_count += 1;
Ok(())
}
async fn shutdown(&mut self) -> Result<(), Mecha10Error> {
assert_eq!(self.run_count, 1);
Ok(())
}
async fn health_check(&self) -> HealthStatus {
HealthStatus {
healthy: true,
last_check: now_micros(),
failure_count: 0,
message: Some(format!("Test node is healthy (run_count: {})", self.run_count)),
}
}
}
#[tokio::test]
async fn test_health_check() {
let config = TestConfig { value: 42 };
let node: Node<TestNode> = Node::from_config(config).await.unwrap();
let health = node.health_check().await;
assert!(health.healthy);
assert!(health.message.is_some());
assert!(health.message.unwrap().contains("healthy"));
}
#[test]
fn test_node_state_checks() {
assert!(matches!(NodeState::Running, NodeState::Running));
assert!(matches!(NodeState::Starting, NodeState::Starting));
assert!(matches!(NodeState::Crashed, NodeState::Crashed));
assert!(matches!(NodeState::Stopped, NodeState::Stopped));
}