use super::*;
use crate::tracing::{ParseEvent, Span};
#[test]
fn test_trace_002_001_default_capacity() {
let buffer = CircularTraceBuffer::new();
assert_eq!(buffer.capacity(), 1024);
assert_eq!(buffer.len(), 0);
assert!(buffer.is_empty());
}
#[test]
fn test_trace_002_002_custom_capacity() {
let buffer = CircularTraceBuffer::with_capacity(512);
assert_eq!(buffer.capacity(), 512);
}
#[test]
fn test_trace_002_003_push_event() {
let mut buffer = CircularTraceBuffer::with_capacity(2);
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test.sh".to_string(),
line: 1,
col: 1,
}));
assert_eq!(buffer.len(), 1);
assert_eq!(buffer.total_events(), 1);
}
#[test]
fn test_trace_002_004_eviction() {
let mut buffer = CircularTraceBuffer::with_capacity(2);
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test1.sh".to_string(),
line: 1,
col: 1,
}));
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test2.sh".to_string(),
line: 1,
col: 1,
}));
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test3.sh".to_string(),
line: 1,
col: 1,
}));
assert_eq!(buffer.len(), 2); assert_eq!(buffer.total_events(), 3); assert_eq!(buffer.evicted_count(), 1); }
#[test]
fn test_trace_002_005_retention_rate() {
let mut buffer = CircularTraceBuffer::with_capacity(2);
assert_eq!(buffer.retention_rate(), 1.0);
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test1.sh".to_string(),
line: 1,
col: 1,
}));
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test2.sh".to_string(),
line: 1,
col: 1,
}));
assert_eq!(buffer.retention_rate(), 1.0);
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test3.sh".to_string(),
line: 1,
col: 1,
}));
assert!((buffer.retention_rate() - 0.6667).abs() < 0.01);
}
#[test]
fn test_trace_002_006_utilization() {
let mut buffer = CircularTraceBuffer::with_capacity(4);
assert_eq!(buffer.utilization(), 0.0);
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test.sh".to_string(),
line: 1,
col: 1,
}));
assert_eq!(buffer.utilization(), 0.25);
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test.sh".to_string(),
line: 1,
col: 1,
}));
assert_eq!(buffer.utilization(), 0.5);
}
#[test]
fn test_trace_002_007_is_full() {
let mut buffer = CircularTraceBuffer::with_capacity(2);
assert!(!buffer.is_full());
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test.sh".to_string(),
line: 1,
col: 1,
}));
assert!(!buffer.is_full());
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test.sh".to_string(),
line: 1,
col: 1,
}));
assert!(buffer.is_full());
}
#[test]
fn test_trace_002_008_clear() {
let mut buffer = CircularTraceBuffer::with_capacity(2);
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test.sh".to_string(),
line: 1,
col: 1,
}));
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test.sh".to_string(),
line: 1,
col: 1,
}));
assert_eq!(buffer.len(), 2);
buffer.clear();
assert_eq!(buffer.len(), 0);
assert_eq!(buffer.total_events(), 0);
}
#[test]
fn test_trace_002_009_iterator() {
let mut buffer = CircularTraceBuffer::with_capacity(3);
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test1.sh".to_string(),
line: 1,
col: 1,
}));
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test2.sh".to_string(),
line: 1,
col: 1,
}));
let events: Vec<_> = buffer.iter().collect();
assert_eq!(events.len(), 2);
}
#[test]
fn test_trace_002_010_filtered_iterator() {
let mut buffer = CircularTraceBuffer::with_capacity(10);
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test.sh".to_string(),
line: 1,
col: 1,
}));
buffer.push(TraceEvent::Parse(ParseEvent::ParseError {
error: "Syntax error".to_string(),
span: Span::single_line(1, 1, 10),
}));
let high_events: Vec<_> = buffer.iter_filtered(TraceSignificance::High).collect();
assert_eq!(high_events.len(), 1);
}
#[test]
fn test_trace_002_011_stats() {
let mut buffer = CircularTraceBuffer::with_capacity(2);
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test.sh".to_string(),
line: 1,
col: 1,
}));
let stats = buffer.stats();
assert_eq!(stats.capacity, 2);
assert_eq!(stats.current_size, 1);
assert_eq!(stats.total_events, 1);
assert_eq!(stats.utilization, 0.5);
}
#[test]
fn test_trace_002_012_serialization() {
let mut buffer = CircularTraceBuffer::with_capacity(2);
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: "test.sh".to_string(),
line: 1,
col: 1,
}));
let json = serde_json::to_string(&buffer).expect("Serialization failed");
let deserialized: CircularTraceBuffer =
serde_json::from_str(&json).expect("Deserialization failed");
assert_eq!(buffer.len(), deserialized.len());
assert_eq!(buffer.capacity(), deserialized.capacity());
}
#[cfg(test)]
mod property_tests {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn prop_trace_002_never_exceeds_capacity(
capacity in 1usize..1000,
push_count in 1usize..2000,
) {
let mut buffer = CircularTraceBuffer::with_capacity(capacity);
for i in 0..push_count {
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: format!("test{}.sh", i),
line: 1,
col: 1,
}));
}
prop_assert!(buffer.len() <= capacity);
}
}
proptest! {
#[test]
fn prop_trace_002_retention_rate_bounds(
capacity in 1usize..100,
push_count in 1usize..200,
) {
let mut buffer = CircularTraceBuffer::with_capacity(capacity);
for i in 0..push_count {
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: format!("test{}.sh", i),
line: 1,
col: 1,
}));
}
let rate = buffer.retention_rate();
prop_assert!((0.0..=1.0).contains(&rate));
}
}
proptest! {
#[test]
fn prop_trace_002_total_vs_current(
capacity in 1usize..100,
push_count in 1usize..200,
) {
let mut buffer = CircularTraceBuffer::with_capacity(capacity);
for i in 0..push_count {
buffer.push(TraceEvent::Parse(ParseEvent::ParseStart {
source: format!("test{}.sh", i),
line: 1,
col: 1,
}));
}
prop_assert!(buffer.total_events() >= buffer.len() as u64);
}
}
}