use canlink_hal::{BackendConfig, CanBackend, CanError, CanId, CanMessage};
use canlink_mock::MockBackend;
#[test]
fn test_error_injection_workflow() {
let mut backend = MockBackend::new();
let config = BackendConfig::new("mock");
backend.initialize(&config).unwrap();
backend.open_channel(0).unwrap();
backend.error_injector_mut().inject_send_error_with_config(
CanError::SendFailed {
reason: "Simulated bus-off".to_string(),
},
1, 2, );
let msg1 = CanMessage::new_standard(0x100, &[1]).unwrap();
assert!(backend.send_message(&msg1).is_ok());
let msg2 = CanMessage::new_standard(0x200, &[2]).unwrap();
assert!(backend.send_message(&msg2).is_ok());
let msg3 = CanMessage::new_standard(0x300, &[3]).unwrap();
let result = backend.send_message(&msg3);
assert!(result.is_err());
match result {
Err(CanError::SendFailed { reason }) => {
assert_eq!(reason, "Simulated bus-off");
}
_ => panic!("Expected SendFailed error"),
}
let msg4 = CanMessage::new_standard(0x400, &[4]).unwrap();
assert!(backend.send_message(&msg4).is_ok());
assert!(backend.verify_message_count(3));
assert!(backend.verify_message_sent(CanId::Standard(0x100)));
assert!(backend.verify_message_sent(CanId::Standard(0x200)));
assert!(!backend.verify_message_sent(CanId::Standard(0x300)));
assert!(backend.verify_message_sent(CanId::Standard(0x400)));
}
#[test]
fn test_preset_messages_workflow() {
let preset_messages = vec![
CanMessage::new_standard(0x111, &[0x11, 0x22]).unwrap(),
CanMessage::new_standard(0x222, &[0x33, 0x44, 0x55]).unwrap(),
CanMessage::new_extended(0x12345678, &[0x66]).unwrap(),
];
let config = canlink_mock::MockConfig::with_preset_messages(preset_messages);
let mut backend = MockBackend::with_config(config);
let backend_config = BackendConfig::new("mock");
backend.initialize(&backend_config).unwrap();
backend.open_channel(0).unwrap();
let msg1 = backend.receive_message().unwrap();
assert!(msg1.is_some());
let msg1 = msg1.unwrap();
assert_eq!(msg1.id(), CanId::Standard(0x111));
assert_eq!(msg1.data(), &[0x11, 0x22]);
let msg2 = backend.receive_message().unwrap();
assert!(msg2.is_some());
let msg2 = msg2.unwrap();
assert_eq!(msg2.id(), CanId::Standard(0x222));
assert_eq!(msg2.data(), &[0x33, 0x44, 0x55]);
let msg3 = backend.receive_message().unwrap();
assert!(msg3.is_some());
let msg3 = msg3.unwrap();
assert_eq!(msg3.id(), CanId::Extended(0x12345678));
assert_eq!(msg3.data(), &[0x66]);
let msg4 = backend.receive_message().unwrap();
assert!(msg4.is_none());
}
#[test]
fn test_message_verification_workflow() {
let mut backend = MockBackend::new();
let config = BackendConfig::new("mock");
backend.initialize(&config).unwrap();
backend.open_channel(0).unwrap();
backend
.send_message(&CanMessage::new_standard(0x100, &[1, 2]).unwrap())
.unwrap();
backend
.send_message(&CanMessage::new_standard(0x200, &[3, 4]).unwrap())
.unwrap();
backend
.send_message(&CanMessage::new_standard(0x100, &[5, 6]).unwrap())
.unwrap();
backend
.send_message(&CanMessage::new_standard(0x300, &[7, 8]).unwrap())
.unwrap();
backend
.send_message(&CanMessage::new_standard(0x100, &[9, 10]).unwrap())
.unwrap();
assert!(backend.verify_message_count(5));
assert!(backend.verify_message_sent(CanId::Standard(0x100)));
assert!(backend.verify_message_sent(CanId::Standard(0x200)));
assert!(backend.verify_message_sent(CanId::Standard(0x300)));
assert!(!backend.verify_message_sent(CanId::Standard(0x400)));
let messages_100 = backend.get_messages_by_id(CanId::Standard(0x100));
assert_eq!(messages_100.len(), 3);
assert_eq!(messages_100[0].data(), &[1, 2]);
assert_eq!(messages_100[1].data(), &[5, 6]);
assert_eq!(messages_100[2].data(), &[9, 10]);
let messages_200 = backend.get_messages_by_id(CanId::Standard(0x200));
assert_eq!(messages_200.len(), 1);
assert_eq!(messages_200[0].data(), &[3, 4]);
let messages_300 = backend.get_messages_by_id(CanId::Standard(0x300));
assert_eq!(messages_300.len(), 1);
assert_eq!(messages_300[0].data(), &[7, 8]);
}
#[test]
fn test_combined_error_injection_and_verification() {
let mut backend = MockBackend::new();
let config = BackendConfig::new("mock");
backend.initialize(&config).unwrap();
backend.open_channel(0).unwrap();
backend.error_injector_mut().inject_send_error_with_config(
CanError::SendFailed {
reason: "Intermittent failure".to_string(),
},
3, 2, );
for i in 0..6 {
let msg = CanMessage::new_standard(0x100 + i as u16, &[i]).unwrap();
let result = backend.send_message(&msg);
if i < 2 {
assert!(result.is_ok(), "Message {} should succeed (skip)", i);
} else if i < 5 {
assert!(result.is_err(), "Message {} should fail (inject)", i);
} else {
assert!(result.is_ok(), "Message {} should succeed (exhausted)", i);
}
}
assert!(backend.verify_message_count(3));
assert!(backend.verify_message_sent(CanId::Standard(0x100))); assert!(backend.verify_message_sent(CanId::Standard(0x101))); assert!(!backend.verify_message_sent(CanId::Standard(0x102))); assert!(!backend.verify_message_sent(CanId::Standard(0x103))); assert!(!backend.verify_message_sent(CanId::Standard(0x104))); assert!(backend.verify_message_sent(CanId::Standard(0x105))); }
#[test]
fn test_mock_state_reset() {
let mut backend = MockBackend::new();
let config = BackendConfig::new("mock");
backend.initialize(&config).unwrap();
backend.open_channel(0).unwrap();
backend
.send_message(&CanMessage::new_standard(0x123, &[1, 2, 3]).unwrap())
.unwrap();
backend
.send_message(&CanMessage::new_standard(0x456, &[4, 5, 6]).unwrap())
.unwrap();
assert!(backend.verify_message_count(2));
backend.clear_recorded_messages();
assert!(backend.verify_message_count(0));
assert!(!backend.verify_message_sent(CanId::Standard(0x123)));
backend
.send_message(&CanMessage::new_standard(0x789, &[7, 8, 9]).unwrap())
.unwrap();
assert!(backend.verify_message_count(1));
assert!(backend.verify_message_sent(CanId::Standard(0x789)));
assert!(!backend.verify_message_sent(CanId::Standard(0x123)));
}
#[test]
fn test_multi_operation_error_injection() {
let mut backend = MockBackend::new();
backend
.error_injector_mut()
.inject_init_error(CanError::InitializationFailed {
reason: "Hardware not found".to_string(),
});
let config = BackendConfig::new("mock");
let result = backend.initialize(&config);
assert!(result.is_err());
backend.error_injector_mut().clear();
assert!(backend.initialize(&config).is_ok());
backend
.error_injector_mut()
.inject_open_channel_error(CanError::ChannelNotFound { channel: 0, max: 1 });
let result = backend.open_channel(0);
assert!(result.is_err());
backend.error_injector_mut().clear();
assert!(backend.open_channel(0).is_ok());
backend
.error_injector_mut()
.inject_receive_error(CanError::ReceiveFailed {
reason: "Buffer overflow".to_string(),
});
let result = backend.receive_message();
assert!(result.is_err());
backend.error_injector_mut().clear();
}
#[test]
fn test_realistic_protocol_testing() {
let mut backend = MockBackend::new();
let config = BackendConfig::new("mock");
backend.initialize(&config).unwrap();
backend.open_channel(0).unwrap();
let request = CanMessage::new_standard(0x7E0, &[0x02, 0x01, 0x00]).unwrap();
backend.send_message(&request).unwrap();
assert!(backend.verify_message_sent(CanId::Standard(0x7E0)));
let requests = backend.get_messages_by_id(CanId::Standard(0x7E0));
assert_eq!(requests.len(), 1);
assert_eq!(requests[0].data(), &[0x02, 0x01, 0x00]);
backend
.error_injector_mut()
.inject_send_error(CanError::SendFailed {
reason: "Bus busy".to_string(),
});
let request2 = CanMessage::new_standard(0x7E0, &[0x02, 0x01, 0x01]).unwrap();
let result = backend.send_message(&request2);
assert!(result.is_err());
backend.error_injector_mut().clear();
backend.send_message(&request2).unwrap();
let all_requests = backend.get_messages_by_id(CanId::Standard(0x7E0));
assert_eq!(all_requests.len(), 2);
assert_eq!(all_requests[0].data(), &[0x02, 0x01, 0x00]);
assert_eq!(all_requests[1].data(), &[0x02, 0x01, 0x01]);
}
#[test]
fn test_canfd_capability_adaptation() {
let mut backend_fd = MockBackend::new();
let config = BackendConfig::new("mock");
backend_fd.initialize(&config).unwrap();
backend_fd.open_channel(0).unwrap();
let capability = backend_fd.get_capability().unwrap();
assert!(capability.supports_canfd);
let data = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
let msg_fd = CanMessage::new_fd(CanId::Standard(0x123), &data).unwrap();
assert!(backend_fd.send_message(&msg_fd).is_ok());
let config_20 = canlink_mock::MockConfig::can20_only();
let mut backend_20 = MockBackend::with_config(config_20);
backend_20.initialize(&config).unwrap();
backend_20.open_channel(0).unwrap();
let capability = backend_20.get_capability().unwrap();
assert!(!capability.supports_canfd);
let result = backend_20.send_message(&msg_fd);
assert!(result.is_err());
match result {
Err(CanError::UnsupportedFeature { feature }) => {
assert_eq!(feature, "CAN-FD");
}
_ => panic!("Expected UnsupportedFeature error"),
}
let msg_20 = CanMessage::new_standard(0x123, &[1, 2, 3]).unwrap();
assert!(backend_20.send_message(&msg_20).is_ok());
}
#[test]
fn test_injection_counter_tracking() {
let mut backend = MockBackend::new();
let config = BackendConfig::new("mock");
backend.initialize(&config).unwrap();
backend.open_channel(0).unwrap();
assert_eq!(backend.error_injector().injection_count(), 0);
backend.error_injector_mut().inject_send_error_with_config(
CanError::SendFailed {
reason: "Test".to_string(),
},
3,
0,
);
for _ in 0..3 {
let msg = CanMessage::new_standard(0x100, &[1]).unwrap();
let _ = backend.send_message(&msg);
}
assert_eq!(backend.error_injector().injection_count(), 3);
backend.error_injector_mut().clear();
assert_eq!(backend.error_injector().injection_count(), 0);
}