use peat_protocol::models::{
AuthorityLevel, BindingType, Capability, CapabilityExt, CapabilityType, CellConfig,
CellConfigExt, CellState, CellStateExt, HumanMachinePair, HumanMachinePairExt, NodeConfig,
NodeConfigExt, NodeState, NodeStateExt, Operator, OperatorExt, OperatorRank,
};
#[test]
fn test_node_to_cell_capability_aggregation() {
let mut node1_config = NodeConfig::new("UAV".to_string());
node1_config.add_capability(Capability::new(
"camera_1".to_string(),
"HD Camera".to_string(),
CapabilityType::Sensor,
0.9,
));
node1_config.add_capability(Capability::new(
"gps_1".to_string(),
"GPS".to_string(),
CapabilityType::Sensor,
0.95,
));
let mut node2_config = NodeConfig::new("UGV".to_string());
node2_config.add_capability(Capability::new(
"compute_1".to_string(),
"Edge Compute".to_string(),
CapabilityType::Compute,
0.85,
));
node2_config.add_capability(Capability::new(
"comm_1".to_string(),
"Radio".to_string(),
CapabilityType::Communication,
0.9,
));
let config = CellConfig::new(5);
let mut cell = CellState::new(config);
cell.add_member(node1_config.id.clone());
cell.add_member(node2_config.id.clone());
for cap in &node1_config.capabilities {
cell.add_capability(cap.clone());
}
for cap in &node2_config.capabilities {
cell.add_capability(cap.clone());
}
assert_eq!(cell.capabilities.len(), 4);
assert!(cell.has_capability_type(CapabilityType::Sensor));
assert!(cell.has_capability_type(CapabilityType::Compute));
assert!(cell.has_capability_type(CapabilityType::Communication));
let sensors = cell.get_capabilities_by_type(CapabilityType::Sensor);
assert_eq!(sensors.len(), 2);
}
#[test]
fn test_human_operated_node_in_cell() {
let operator = Operator::new(
"op_1".to_string(),
"SSG Smith".to_string(),
OperatorRank::E6,
AuthorityLevel::Commander,
"11B".to_string(),
);
let binding = HumanMachinePair::new(
vec![operator],
vec!["soldier_system_1".to_string()],
BindingType::OneToOne,
);
let node_config = NodeConfig::with_operator("Soldier System".to_string(), binding);
assert!(node_config.is_human_operated());
assert!(!node_config.is_autonomous());
let config = CellConfig::new(4);
let mut cell = CellState::new(config);
cell.add_member(node_config.id.clone());
cell.set_leader(node_config.id.clone()).unwrap();
assert!(cell.is_leader(&node_config.id));
assert_eq!(cell.member_count(), 1);
}
#[test]
fn test_mixed_autonomous_and_human_operated_cell() {
let mut auto1 = NodeConfig::new("Robot 1".to_string());
auto1.add_capability(Capability::new(
"mobility_1".to_string(),
"Mobility".to_string(),
CapabilityType::Mobility,
0.9,
));
let mut auto2 = NodeConfig::new("Robot 2".to_string());
auto2.add_capability(Capability::new(
"sensor_1".to_string(),
"Sensor".to_string(),
CapabilityType::Sensor,
0.85,
));
let operator = Operator::new(
"op_1".to_string(),
"SFC Davis".to_string(),
OperatorRank::E7,
AuthorityLevel::Supervisor,
"11B".to_string(),
);
let binding = HumanMachinePair::one_to_one(operator, "command_node_1".to_string());
let human_node = NodeConfig::with_operator("Command Node".to_string(), binding);
let config = CellConfig::new(5);
let mut cell = CellState::new(config);
cell.add_member(auto1.id.clone());
cell.add_member(auto2.id.clone());
cell.add_member(human_node.id.clone());
cell.set_leader(human_node.id.clone()).unwrap();
for cap in &auto1.capabilities {
cell.add_capability(cap.clone());
}
for cap in &auto2.capabilities {
cell.add_capability(cap.clone());
}
assert_eq!(cell.member_count(), 3);
assert_eq!(cell.capabilities.len(), 2);
assert!(cell.is_leader(&human_node.id));
}
#[test]
fn test_operator_cognitive_load_affects_cell_readiness() {
let mut operator = Operator::new(
"op_1".to_string(),
"CPL Johnson".to_string(),
OperatorRank::E4,
AuthorityLevel::Supervisor,
"11B".to_string(),
);
operator.update_cognitive_load(0.95);
operator.update_fatigue(0.85);
let binding = HumanMachinePair::one_to_one(operator.clone(), "node_1".to_string());
assert!(operator.is_overloaded(0.9));
assert!(operator.is_fatigued(0.8));
assert!(binding.has_overloaded_operator(0.9));
let effectiveness = binding.avg_effectiveness();
assert!(effectiveness < 0.5); }
#[test]
fn test_node_state_synchronization_in_cell() {
let node1_config = NodeConfig::new("Node 1".to_string());
let node2_config = NodeConfig::new("Node 2".to_string());
let mut state1 = NodeState::new((37.7, -122.4, 100.0));
let mut state2 = NodeState::new((37.8, -122.5, 150.0));
state1.assign_cell("cell_1".to_string());
state2.assign_cell("cell_1".to_string());
assert_eq!(state1.cell_id, Some("cell_1".to_string()));
assert_eq!(state2.cell_id, Some("cell_1".to_string()));
let config = CellConfig::with_id("cell_1".to_string(), 5);
let mut cell = CellState::new(config);
cell.add_member(node1_config.id.clone());
cell.add_member(node2_config.id.clone());
assert!(cell.is_valid());
assert_eq!(cell.member_count(), 2);
}
#[test]
fn test_cell_merge_with_node_states() {
let node1_config = NodeConfig::new("Node 1".to_string());
let mut state1 = NodeState::new((37.7, -122.4, 100.0));
state1.assign_cell("cell_1".to_string());
let config = CellConfig::with_id("cell_1".to_string(), 5);
let mut cell1 = CellState::new(config);
cell1.add_member(node1_config.id.clone());
let node2_config = NodeConfig::new("Node 2".to_string());
let mut state2 = NodeState::new((37.8, -122.5, 150.0));
state2.assign_cell("cell_2".to_string());
let config2 = CellConfig::with_id("cell_2".to_string(), 5);
let mut cell2 = CellState::new(config2);
cell2.add_member(node2_config.id.clone());
cell1.merge(&cell2);
assert_eq!(cell1.member_count(), 2);
assert!(cell1.is_member(&node1_config.id));
assert!(cell1.is_member(&node2_config.id));
}
#[test]
fn test_capability_validation_across_models() {
let low_confidence_cap = Capability::new(
"sensor_1".to_string(),
"Degraded Sensor".to_string(),
CapabilityType::Sensor,
0.3,
);
assert!(!low_confidence_cap.is_valid(0.5));
let mut node = NodeConfig::new("Node 1".to_string());
node.add_capability(low_confidence_cap.clone());
assert_eq!(node.capabilities.len(), 1);
let config = CellConfig::new(5);
let mut cell = CellState::new(config);
cell.add_capability(low_confidence_cap);
assert_eq!(cell.capabilities.len(), 1);
}
#[test]
fn test_multiple_operators_in_cell_leader_selection() {
let commander = Operator::new(
"op_1".to_string(),
"CPT Williams".to_string(),
OperatorRank::O3,
AuthorityLevel::Commander,
"11A".to_string(),
);
let nco = Operator::new(
"op_2".to_string(),
"SFC Davis".to_string(),
OperatorRank::E7,
AuthorityLevel::Supervisor,
"11B".to_string(),
);
let binding1 = HumanMachinePair::one_to_one(commander, "node_1".to_string());
let node1 = NodeConfig::with_operator("Command Node".to_string(), binding1);
let binding2 = HumanMachinePair::one_to_one(nco, "node_2".to_string());
let node2 = NodeConfig::with_operator("NCO Node".to_string(), binding2);
let config = CellConfig::new(5);
let mut cell = CellState::new(config);
cell.add_member(node1.id.clone());
cell.add_member(node2.id.clone());
cell.set_leader(node1.id.clone()).unwrap();
assert!(cell.is_leader(&node1.id));
assert_eq!(
node1.get_primary_operator().unwrap().rank,
OperatorRank::O3 as i32
);
assert_eq!(
node2.get_primary_operator().unwrap().rank,
OperatorRank::E7 as i32
);
}
#[test]
fn test_protobuf_serialization_roundtrip() {
let mut operator = Operator::new(
"op_1".to_string(),
"Test Operator".to_string(),
OperatorRank::E5,
AuthorityLevel::Supervisor,
"11B".to_string(),
);
operator.update_cognitive_load(0.6);
operator.update_fatigue(0.4);
let binding = HumanMachinePair::one_to_one(operator.clone(), "node_1".to_string());
let mut node = NodeConfig::with_operator("Test Node".to_string(), binding);
node.add_capability(Capability::new(
"cap_1".to_string(),
"Test Cap".to_string(),
CapabilityType::Sensor,
0.85,
));
assert_eq!(node.platform_type, "Test Node");
assert!(node.operator_binding.is_some());
assert_eq!(node.capabilities.len(), 1);
let retrieved_binding = node.operator_binding.as_ref().unwrap();
assert_eq!(retrieved_binding.operators.len(), 1);
assert_eq!(retrieved_binding.operators[0].id, "op_1");
let retrieved_op = &retrieved_binding.operators[0];
assert_eq!(retrieved_op.cognitive_load(), 0.6);
assert_eq!(retrieved_op.fatigue(), 0.4);
}
#[test]
fn test_cell_with_empty_operator_binding() {
let binding =
HumanMachinePair::new(vec![], vec!["node_1".to_string()], BindingType::Unspecified);
let node = NodeConfig::with_operator("Autonomous Node".to_string(), binding);
assert!(node.is_autonomous());
assert!(!node.is_human_operated());
let config = CellConfig::new(5);
let mut cell = CellState::new(config);
cell.add_member(node.id.clone());
assert_eq!(cell.member_count(), 1);
}
#[test]
fn test_node_state_merge_preserves_cell_assignment() {
let mut state1 = NodeState::new((37.7, -122.4, 100.0));
state1.assign_cell("cell_1".to_string());
let mut state2 = state1.clone();
std::thread::sleep(std::time::Duration::from_secs(1));
state2.update_position((37.8, -122.5, 150.0));
state2.assign_cell("cell_2".to_string());
let ts1 = state1.timestamp.as_ref().map(|t| t.seconds).unwrap_or(0);
let ts2 = state2.timestamp.as_ref().map(|t| t.seconds).unwrap_or(0);
assert!(ts2 > ts1, "state2 timestamp should be newer");
state1.merge(&state2);
assert_eq!(state1.cell_id, Some("cell_2".to_string()));
assert_eq!(state1.get_position(), (37.8, -122.5, 150.0));
}