use sorting_race::models::traits::MemoryTracker;
use sorting_race::services::memory::StandardMemoryTracker;
#[derive(Debug, Default)]
struct TestMemoryTracker {
current: usize,
peak: usize,
}
impl MemoryTracker for TestMemoryTracker {
fn alloc(&mut self, bytes: usize) {
self.current += bytes;
self.peak = self.peak.max(self.current);
}
fn free(&mut self, bytes: usize) {
self.current = self.current.saturating_sub(bytes);
}
fn current(&self) -> usize {
self.current
}
fn peak(&self) -> usize {
self.peak
}
fn reset(&mut self) {
self.current = 0;
self.peak = 0;
}
}
#[cfg(test)]
mod tests {
use super::*;
fn verify_memory_tracker<T: MemoryTracker>(mut tracker: T) {
assert_eq!(tracker.current(), 0);
assert_eq!(tracker.peak(), 0);
tracker.alloc(100);
assert_eq!(tracker.current(), 100);
assert_eq!(tracker.peak(), 100);
tracker.alloc(50);
assert_eq!(tracker.current(), 150);
assert_eq!(tracker.peak(), 150);
tracker.free(75);
assert_eq!(tracker.current(), 75);
assert_eq!(tracker.peak(), 150);
tracker.alloc(50);
assert_eq!(tracker.current(), 125);
assert_eq!(tracker.peak(), 150);
tracker.alloc(100);
assert_eq!(tracker.current(), 225);
assert_eq!(tracker.peak(), 225);
tracker.free(225);
assert_eq!(tracker.current(), 0);
assert_eq!(tracker.peak(), 225);
tracker.reset();
assert_eq!(tracker.current(), 0);
assert_eq!(tracker.peak(), 0);
}
#[test]
fn test_test_memory_tracker() {
let tracker = TestMemoryTracker::default();
verify_memory_tracker(tracker);
}
#[test]
fn test_standard_memory_tracker() {
let tracker = StandardMemoryTracker::new();
verify_memory_tracker(tracker);
}
#[test]
fn test_memory_tracker_overflow_protection() {
let mut tracker = TestMemoryTracker::default();
tracker.alloc(usize::MAX / 2);
assert_eq!(tracker.current(), usize::MAX / 2);
tracker.alloc(usize::MAX / 2 + 100);
assert!(tracker.current() > 0);
tracker.free(usize::MAX);
assert_eq!(tracker.current(), 0);
}
#[test]
fn test_memory_tracker_sequence() {
let mut tracker = StandardMemoryTracker::new();
let stack_frames = vec![16, 16, 16, 16]; for size in &stack_frames {
tracker.alloc(*size);
}
assert_eq!(tracker.current(), 64);
assert_eq!(tracker.peak(), 64);
for size in stack_frames.iter().rev() {
tracker.free(*size);
}
assert_eq!(tracker.current(), 0);
assert_eq!(tracker.peak(), 64);
}
#[test]
fn test_memory_tracker_merge_buffer() {
let mut tracker = StandardMemoryTracker::new();
let buffer_size = 1000;
tracker.alloc(buffer_size);
assert_eq!(tracker.current(), buffer_size);
assert_eq!(tracker.peak(), buffer_size);
tracker.free(buffer_size);
assert_eq!(tracker.current(), 0);
assert_eq!(tracker.peak(), buffer_size);
}
#[test]
fn test_memory_tracker_multiple_algorithms() {
let mut trackers: Vec<Box<dyn MemoryTracker>> = vec![
Box::new(TestMemoryTracker::default()), Box::new(StandardMemoryTracker::new()), Box::new(StandardMemoryTracker::new()), ];
trackers[0].alloc(8);
trackers[1].alloc(64);
trackers[2].alloc(400);
assert_eq!(trackers[0].current(), 8);
assert_eq!(trackers[1].current(), 64);
assert_eq!(trackers[2].current(), 400);
let total_current: usize = trackers.iter().map(|t| t.current()).sum();
let total_peak: usize = trackers.iter().map(|t| t.peak()).sum();
assert_eq!(total_current, 472);
assert_eq!(total_peak, 472);
}
#[test]
fn test_memory_tracker_reset_behavior() {
let mut tracker = StandardMemoryTracker::new();
tracker.alloc(100);
tracker.alloc(200);
tracker.free(150);
assert_eq!(tracker.current(), 150);
assert_eq!(tracker.peak(), 300);
tracker.reset();
assert_eq!(tracker.current(), 0);
assert_eq!(tracker.peak(), 0);
tracker.alloc(50);
assert_eq!(tracker.current(), 50);
assert_eq!(tracker.peak(), 50);
}
}