use pretty_assertions::assert_eq; use tracing::Level; use serde_json::Map; use serde::{Serialize, Deserialize}; use super::*; #[test] fn test_logger_sequential_consistency() { use std::sync::atomic::{AtomicUsize, Ordering}; use tracing::{debug, error, info, trace, warn}; let config = LoggerConfig::default() .log_to_stdout(true) .log_to_file(true); let logger = Logger::new(config); static COUNTER: AtomicUsize = AtomicUsize::new(0); for i in 0..4096 * 128 { let count = COUNTER.fetch_add(1, Ordering::SeqCst); match i % 5 { 0 => error!("Error message {}", count), 1 => warn!("Warning message {}", count), 2 => info!("Info message {}", count), 3 => debug!("Debug message {}", count), _ => trace!("Trace message {}", count), } } let logs = logger.get_logs(LogQuery::All); assert_eq!( logs.len(), 4096 * 128, "Should have exactly 5000 log entries" ); for (i, log) in logs.iter().enumerate() { let expected_count = i; let expected_level = match i % 5 { 0 => Level::ERROR, 1 => Level::WARN, 2 => Level::INFO, 3 => Level::DEBUG, _ => Level::TRACE, }; assert_eq!( log.level, expected_level, "Log {} has incorrect level: {:?}", i, log.level ); let expected_msg = match expected_level { Level::ERROR => format!("Error message {}", expected_count), Level::WARN => format!("Warning message {}", expected_count), Level::INFO => format!("Info message {}", expected_count), Level::DEBUG => format!("Debug message {}", expected_count), Level::TRACE => format!("Trace message {}", expected_count), }; assert_eq!( log.message, expected_msg, "Log {} has incorrect message. Expected: '{}', Got: '{}'", i, expected_msg, log.message ); if i > 0 { assert!( log.timestamp >= logs[i - 1].timestamp, "Log {} has timestamp out of order. Current: {:?}, Previous: {:?}", i, log.timestamp, logs[i - 1].timestamp ); } } let mut counts: Vec = logs .iter() .map(|log| { log.message .split_whitespace() .last() .unwrap() .parse::() .unwrap() }) .collect(); counts.sort(); counts.dedup(); assert_eq!(counts.len(), 4096 * 128, "Found duplicate log entries"); } #[test] fn test_logger_sequential_consistency_json() { use std::sync::atomic::{AtomicUsize, Ordering}; use tracing::{debug, error, info, trace, warn}; let config = LoggerConfig::default() .log_to_stdout(false) .log_to_file(false) .log_use_json(true) .log_json_show_timestamp(true) .log_json_show_level(true) .log_json_show_message(true) .log_json_show_additional_fields(false); // Not implemented yet let logger = Logger::new(config); static COUNTER: AtomicUsize = AtomicUsize::new(0); for i in 0..4096 * 128 { let count = COUNTER.fetch_add(1, Ordering::SeqCst); match i % 5 { 0 => error!("Error message {}", count), 1 => warn!("Warning message {}", count), 2 => info!("Info message {}", count), 3 => debug!("Debug message {}", count), _ => trace!("Trace message {}", count), } } let mut log_json: Vec> = vec![]; for log in logger.get_logs(LogQuery::All) { let mut json_object = serde_json::Map::new(); json_object.insert("timestamp".to_string(), Value::String(DateTime::::from(log.timestamp).to_rfc3339())); json_object.insert("level".to_string(), Value::String(log.level.to_string())); json_object.insert("message".to_string(), Value::String(log.message.to_string())); log_json.push(json_object); } for log in log_json { serde_json::to_string(&log).unwrap(); } }