use rustc_hash::{FxHashMap, FxHashSet};
use timberjack::analyzer::AnalysisResult;
#[cfg(test)]
use timberjack::formatter::print_results_to_writer;
#[test]
fn test_print_basic_results() {
let mut result = AnalysisResult {
matched_lines: vec![
"2025-03-21 14:00:00,123 [ERROR] NullPointerException".to_string(),
"2025-03-21 14:03:00,012 [ERROR] Connection timeout".to_string(),
],
count: 2,
time_trends: FxHashMap::default(),
levels_count: FxHashMap::default(),
error_types: FxHashMap::default(),
unique_messages: FxHashSet::default(),
deduplicated: false,
line_counts: FxHashMap::default(),
};
result.levels_count.insert("ERROR".to_string(), 2);
let mut output = Vec::new();
print_results_to_writer(&result, false, false, &mut output, 5, false).unwrap();
let output_str = String::from_utf8(output).unwrap();
assert!(output_str.contains("NullPointerException"));
assert!(output_str.contains("Connection timeout"));
assert!(output_str.contains("Felled: 2 logs"));
}
#[test]
fn test_print_trend_results() {
let mut result = AnalysisResult {
matched_lines: vec![
"2025-03-21 14:00:00,123 [ERROR] NullPointerException".to_string(),
"2025-03-21 15:03:00,012 [ERROR] Connection timeout".to_string(),
],
count: 2,
time_trends: FxHashMap::default(),
levels_count: FxHashMap::default(),
error_types: FxHashMap::default(),
unique_messages: FxHashSet::default(),
deduplicated: false,
line_counts: FxHashMap::default(),
};
result.time_trends.insert("2025-03-21 14".to_string(), 1);
result.time_trends.insert("2025-03-21 15".to_string(), 1);
let mut output = Vec::new();
print_results_to_writer(&result, true, false, &mut output, 5, false).unwrap();
let output_str = String::from_utf8(output).unwrap();
assert!(output_str.contains("Time trends:"));
assert!(output_str.contains("2025-03-21 14 - 1 log occurred"));
assert!(output_str.contains("2025-03-21 15 - 1 log occurred"));
}
#[test]
fn test_print_stats_results() {
let mut result = AnalysisResult {
matched_lines: vec![
"2025-03-21 14:00:00,123 [ERROR] ServiceA - NullPointerException".to_string(),
"2025-03-21 14:01:00,456 [WARN] ServiceB - Slow database query".to_string(),
"2025-03-21 14:03:00,012 [ERROR] ServiceC - Connection timeout".to_string(),
],
count: 3,
time_trends: FxHashMap::default(),
levels_count: FxHashMap::default(),
error_types: FxHashMap::default(),
unique_messages: FxHashSet::default(),
deduplicated: false,
line_counts: FxHashMap::default(),
};
result.levels_count.insert("ERROR".to_string(), 2);
result.levels_count.insert("WARN".to_string(), 1);
result
.error_types
.insert("NullPointerException".to_string(), 1);
result
.error_types
.insert("Connection timeout".to_string(), 1);
result
.unique_messages
.insert("NullPointerException".to_string());
result
.unique_messages
.insert("Slow database query".to_string());
result
.unique_messages
.insert("Connection timeout".to_string());
let mut output = Vec::new();
print_results_to_writer(&result, false, true, &mut output, 5, false).unwrap();
let output_str = String::from_utf8(output).unwrap();
assert!(output_str.contains("Stats summary:"));
assert!(output_str.contains("Log levels:"));
assert!(output_str.contains("ERROR: 2 logs"));
assert!(output_str.contains("WARN: 1 log"));
assert!(output_str.contains("Top error types:"));
assert!(output_str.contains("NullPointerException: 1 occurrence"));
assert!(output_str.contains("Connection timeout: 1 occurrence"));
assert!(output_str.contains("Unique messages: 3"));
assert!(output_str.contains("Repetition ratio: 0.0%"));
}
#[test]
fn test_empty_results() {
let result = AnalysisResult {
matched_lines: vec![],
count: 0,
time_trends: FxHashMap::default(),
levels_count: FxHashMap::default(),
error_types: FxHashMap::default(),
unique_messages: FxHashSet::default(),
deduplicated: false,
line_counts: FxHashMap::default(),
};
let mut output = Vec::new();
print_results_to_writer(&result, true, true, &mut output, 5, false).unwrap();
let output_str = String::from_utf8(output).unwrap();
assert!(output_str.contains("Felled: 0 logs"));
assert!(!output_str.contains("Time trends:"));
assert!(output_str.contains("Stats summary:"));
}
#[test]
fn test_show_unique_messages() {
let mut result = AnalysisResult {
matched_lines: vec![
"2025-03-21 14:00:00,123 [ERROR] ServiceA - NullPointerException".to_string(),
"2025-03-21 14:01:00,456 [WARN] ServiceB - Slow database query".to_string(),
"2025-03-21 14:03:00,012 [ERROR] ServiceC - Connection timeout".to_string(),
],
count: 3,
time_trends: FxHashMap::default(),
levels_count: FxHashMap::default(),
error_types: FxHashMap::default(),
unique_messages: FxHashSet::default(),
deduplicated: false,
line_counts: FxHashMap::default(),
};
result
.unique_messages
.insert("NullPointerException".to_string());
result
.unique_messages
.insert("Slow database query".to_string());
result
.unique_messages
.insert("Connection timeout".to_string());
let mut output = Vec::new();
print_results_to_writer(&result, false, true, &mut output, 5, true).unwrap();
let output_str = String::from_utf8(output).unwrap();
assert!(output_str.contains("Unique messages:"));
assert!(output_str.contains("- NullPointerException"));
assert!(output_str.contains("- Slow database query"));
assert!(output_str.contains("- Connection timeout"));
}
#[test]
fn test_top_errors_limit() {
let mut result = AnalysisResult {
matched_lines: vec![],
count: 10,
time_trends: FxHashMap::default(),
levels_count: FxHashMap::default(),
error_types: FxHashMap::default(),
unique_messages: FxHashSet::default(),
deduplicated: false,
line_counts: FxHashMap::default(),
};
result.error_types.insert("Error1".to_string(), 10);
result.error_types.insert("Error2".to_string(), 9);
result.error_types.insert("Error3".to_string(), 8);
result.error_types.insert("Error4".to_string(), 7);
result.error_types.insert("Error5".to_string(), 6);
result.error_types.insert("Error6".to_string(), 5);
result.error_types.insert("Error7".to_string(), 4);
result.error_types.insert("Error8".to_string(), 3);
let mut output = Vec::new();
print_results_to_writer(&result, false, true, &mut output, 5, false).unwrap();
let output_str = String::from_utf8(output).unwrap();
assert!(output_str.contains("Error1"));
assert!(output_str.contains("Error5"));
assert!(!output_str.contains("Error6"));
let mut output = Vec::new();
print_results_to_writer(&result, false, true, &mut output, 8, false).unwrap();
let output_str = String::from_utf8(output).unwrap();
assert!(output_str.contains("Error8")); }