use canlink_hal::{
filter::{FilterChain, IdFilter, RangeFilter},
queue::{BoundedQueue, QueueOverflowPolicy},
BackendConfig, CanBackend, CanMessage,
};
use canlink_mock::{MockBackend, MockConfig};
#[test]
fn test_queue_memory_stability() {
let iterations = 10000;
let queue_capacity = 100;
{
let mut queue = BoundedQueue::with_policy(queue_capacity, QueueOverflowPolicy::DropOldest);
for i in 0..1000 {
let msg = CanMessage::new_standard((i % 0x7FF) as u16, &[i as u8]).unwrap();
let _ = queue.push(msg);
}
for _ in 0..1000 {
let _ = queue.pop();
}
}
let mut queue = BoundedQueue::with_policy(queue_capacity, QueueOverflowPolicy::DropOldest);
for iteration in 0..iterations {
for i in 0..10 {
let msg = CanMessage::new_standard(((iteration * 10 + i) % 0x7FF) as u16, &[i as u8])
.unwrap();
let _ = queue.push(msg);
}
for _ in 0..10 {
let _ = queue.pop();
}
assert!(
queue.len() <= queue_capacity,
"Queue exceeded capacity at iteration {}",
iteration
);
}
let stats = queue.stats();
assert!(stats.enqueued > 0, "No messages were enqueued");
assert!(stats.dequeued > 0, "No messages were dequeued");
let msg = CanMessage::new_standard(0x123, &[1, 2, 3]).unwrap();
assert!(
queue.push(msg).is_ok(),
"Queue should still accept messages"
);
}
#[test]
fn test_filter_chain_memory_stability() {
let iterations = 1000;
for _ in 0..iterations {
let mut chain = FilterChain::new(8);
chain.add_filter(Box::new(IdFilter::new(0x123)));
chain.add_filter(Box::new(IdFilter::with_mask(0x100, 0x700)));
chain.add_filter(Box::new(RangeFilter::new(0x200, 0x2FF)));
let msg1 = CanMessage::new_standard(0x123, &[1, 2, 3]).unwrap();
let msg2 = CanMessage::new_standard(0x456, &[4, 5, 6]).unwrap();
assert!(chain.matches(&msg1));
assert!(!chain.matches(&msg2));
chain.clear();
assert!(chain.is_empty());
chain.add_filter(Box::new(IdFilter::new(0x456)));
assert!(chain.matches(&msg2));
}
}
#[test]
fn test_backend_message_cycling_stability() {
let iterations = 10000;
let config = MockConfig {
max_recorded_messages: 100,
..MockConfig::default()
};
let mut backend = MockBackend::with_config(config);
let backend_config = BackendConfig::new("mock");
backend.initialize(&backend_config).unwrap();
backend.open_channel(0).unwrap();
for i in 0..iterations {
let msg = CanMessage::new_standard((i % 0x7FF) as u16, &[i as u8, (i >> 8) as u8]).unwrap();
backend.send_message(&msg).unwrap();
if i % 1000 == 999 {
backend.clear_recorded_messages();
}
}
let recorded = backend.get_recorded_messages();
assert!(
recorded.len() <= 100,
"Recorded messages exceeded limit: {}",
recorded.len()
);
backend.close().unwrap();
}
#[test]
fn test_filter_with_backend_stability() {
let iterations = 5000;
let preset: Vec<CanMessage> = (0..10000)
.map(|i| CanMessage::new_standard((i % 0x7FF) as u16, &[i as u8]).unwrap())
.collect();
let config = MockConfig::with_preset_messages(preset);
let mut backend = MockBackend::with_config(config);
let backend_config = BackendConfig::new("mock");
backend.initialize(&backend_config).unwrap();
backend.open_channel(0).unwrap();
backend.add_id_filter(0x123);
backend.add_range_filter(0x200, 0x2FF);
let mut received_count = 0;
for _ in 0..iterations {
if let Ok(Some(_msg)) = backend.receive_message() {
received_count += 1;
}
}
assert!(
received_count < iterations,
"Filter didn't filter any messages"
);
backend.close().unwrap();
}
#[test]
fn test_queue_overflow_policies_stability() {
let iterations = 10000;
let capacity = 50;
{
let mut queue = BoundedQueue::with_policy(capacity, QueueOverflowPolicy::DropOldest);
for i in 0..iterations {
let msg = CanMessage::new_standard((i % 0x7FF) as u16, &[i as u8]).unwrap();
let _ = queue.push(msg);
}
assert_eq!(queue.len(), capacity);
let stats = queue.stats();
assert_eq!(stats.dropped as usize, iterations - capacity);
}
{
let mut queue = BoundedQueue::with_policy(capacity, QueueOverflowPolicy::DropNewest);
for i in 0..iterations {
let msg = CanMessage::new_standard((i % 0x7FF) as u16, &[i as u8]).unwrap();
let _ = queue.push(msg);
}
assert_eq!(queue.len(), capacity);
let stats = queue.stats();
assert_eq!(stats.dropped as usize, iterations - capacity);
}
}
#[test]
fn test_repeated_init_close_stability() {
let iterations = 100;
for _ in 0..iterations {
let mut backend = MockBackend::new();
let config = BackendConfig::new("mock");
backend.initialize(&config).unwrap();
backend.open_channel(0).unwrap();
for i in 0..100 {
let msg = CanMessage::new_standard((i % 0x7FF) as u16, &[i as u8]).unwrap();
backend.send_message(&msg).unwrap();
}
backend.close().unwrap();
}
}
#[test]
fn test_message_creation_stability() {
let iterations = 100000;
for i in 0..iterations {
let _std_msg = CanMessage::new_standard((i % 0x7FF) as u16, &[i as u8]).unwrap();
let _ext_msg = CanMessage::new_extended(i % 0x1FFFFFFF, &[i as u8]).unwrap();
}
}
#[test]
fn test_extended_operation_stability() {
let cycles = 100;
let operations_per_cycle = 1000;
let mut cycle_stats: Vec<(u64, u64)> = Vec::new();
for cycle in 0..cycles {
let mut queue = BoundedQueue::with_policy(100, QueueOverflowPolicy::DropOldest);
let mut chain = FilterChain::new(8);
chain.add_filter(Box::new(IdFilter::new(0x123)));
chain.add_filter(Box::new(RangeFilter::new(0x100, 0x1FF)));
for i in 0..operations_per_cycle {
let msg = CanMessage::new_standard((i % 0x7FF) as u16, &[i as u8]).unwrap();
let _ = chain.matches(&msg);
let _ = queue.push(msg);
if i % 2 == 0 {
let _ = queue.pop();
}
}
let stats = queue.stats();
cycle_stats.push((stats.enqueued, stats.dropped));
assert_eq!(
stats.enqueued as usize, operations_per_cycle,
"Cycle {}: unexpected push count",
cycle
);
}
let first_stats = cycle_stats[0];
for (i, stats) in cycle_stats.iter().enumerate() {
assert_eq!(
stats.0, first_stats.0,
"Cycle {} had different push count",
i
);
}
}