pub mod exporter;
pub mod plot_data;
pub mod tensorboard_exporter;
pub mod trend_analyzer;
pub use exporter::PerformanceExporter;
pub use plot_data::PlotData;
pub use tensorboard_exporter::TensorBoardExporter;
pub use trend_analyzer::{TrendAnalysis, TrendAnalyzer, TrendDirection};
#[cfg(test)]
mod tests {
use super::super::core::PerformanceMeasurement;
use super::super::reporting::PerformanceReport;
use super::*;
use std::time::Duration;
fn create_test_measurement(operation: &str, duration_ms: u64) -> PerformanceMeasurement {
let mut measurement = PerformanceMeasurement::new(operation.to_string());
measurement.duration = Duration::from_millis(duration_ms);
measurement.memory_before = 1000;
measurement.memory_after = 1100;
measurement.peak_memory = 1200;
measurement
}
fn create_test_report() -> PerformanceReport {
let mut report = PerformanceReport::new();
report.add_measurement(&create_test_measurement("op1", 100));
report.add_measurement(&create_test_measurement("op2", 200));
report.add_measurement(&create_test_measurement("op1", 150));
report
}
#[test]
fn test_csv_export() {
let report = create_test_report();
let csv = PerformanceExporter::to_csv(&report);
assert!(csv.is_ok());
let csv_data = csv.expect("operation should succeed");
assert!(csv_data.contains("operation,count,total_time_ms"));
assert!(csv_data.contains("op1"));
assert!(csv_data.contains("op2"));
}
#[test]
fn test_json_export() {
let report = create_test_report();
let json = PerformanceExporter::to_json(&report);
assert!(json.is_ok());
let json_data = json.expect("operation should succeed");
assert!(json_data.contains("total_measurements"));
assert!(json_data.contains("operations"));
}
#[test]
fn test_measurements_csv_export() {
let measurements = vec![
create_test_measurement("test1", 100),
create_test_measurement("test2", 200),
];
let csv = PerformanceExporter::measurements_to_csv(&measurements);
assert!(csv.is_ok());
let csv_data = csv.expect("operation should succeed");
assert!(csv_data.contains("operation,duration_ms"));
assert!(csv_data.contains("test1,100.000"));
assert!(csv_data.contains("test2,200.000"));
}
#[test]
fn test_plot_data_generation() {
let report = create_test_report();
let plot_data = PerformanceExporter::generate_plot_data(&report);
assert_eq!(plot_data.operation_names.len(), 2);
assert_eq!(plot_data.avg_times.len(), 2);
assert_eq!(plot_data.throughputs.len(), 2);
assert_eq!(plot_data.memory_usage.len(), 2);
assert!(plot_data.operation_names.contains(&"op1".to_string()));
assert!(plot_data.operation_names.contains(&"op2".to_string()));
}
#[test]
fn test_plot_data_manipulation() {
let mut plot_data = PlotData::new();
assert!(plot_data.operation_names.is_empty());
plot_data.add_point("test_op".to_string(), 100.0, 10.0, 1024.0);
assert_eq!(plot_data.operation_names.len(), 1);
assert_eq!(plot_data.avg_times[0], 100.0);
assert_eq!(plot_data.throughputs[0], 10.0);
assert_eq!(plot_data.memory_usage[0], 1024.0);
let time_series = plot_data.time_series_data();
assert_eq!(time_series.len(), 1);
}
#[test]
fn test_trend_analyzer_creation() {
let analyzer = TrendAnalyzer::new();
let summary = analyzer.get_trend_summary();
assert!(summary.is_empty()); }
#[test]
fn test_trend_analyzer_add_report() {
let mut analyzer = TrendAnalyzer::new();
let report = create_test_report();
analyzer.add_report(report);
let summary = analyzer.get_trend_summary();
assert!(summary.is_empty());
}
#[test]
fn test_trend_analysis_insufficient_data() {
let analyzer = TrendAnalyzer::new();
let trend = analyzer.analyze_operation_trend("op1");
assert!(trend.is_none()); }
#[test]
fn test_trend_analysis_with_data() {
let mut analyzer = TrendAnalyzer::new();
let mut report1 = PerformanceReport::new();
report1.add_measurement(&create_test_measurement("op1", 100));
analyzer.add_report(report1);
let mut report2 = PerformanceReport::new();
report2.add_measurement(&create_test_measurement("op1", 200)); analyzer.add_report(report2);
let trend = analyzer.analyze_operation_trend("op1");
assert!(trend.is_some());
let trend_analysis = trend.expect("operation should succeed");
assert_eq!(trend_analysis.operation, "op1");
assert_eq!(trend_analysis.trend_direction, TrendDirection::Declining);
assert!(trend_analysis.performance_change_percent < 0.0); }
#[test]
fn test_regression_detection() {
let mut analyzer = TrendAnalyzer::new();
let mut report1 = PerformanceReport::new();
report1.add_measurement(&create_test_measurement("slow_op", 100));
analyzer.add_report(report1);
let mut report2 = PerformanceReport::new();
report2.add_measurement(&create_test_measurement("slow_op", 150));
analyzer.add_report(report2);
let mut report3 = PerformanceReport::new();
report3.add_measurement(&create_test_measurement("slow_op", 200));
analyzer.add_report(report3);
let regressions = analyzer.detect_regressions(20.0); assert!(regressions.is_empty() || !regressions.is_empty()); }
#[test]
fn test_tensorboard_exporter_creation() {
let exporter = TensorBoardExporter::new();
assert_eq!(exporter.step_counter(), 0);
}
#[test]
fn test_tensorboard_step_counter() {
let mut exporter = TensorBoardExporter::new();
assert_eq!(exporter.step_counter(), 0);
exporter.reset_step_counter();
assert_eq!(exporter.step_counter(), 0);
}
#[test]
fn test_trend_analysis_description() {
let analysis = TrendAnalysis {
operation: "test_op".to_string(),
trend_direction: TrendDirection::Improving,
trend_strength: 0.8,
performance_change_percent: 15.0,
data_points: 5,
confidence: 0.9,
};
let description = analysis.description();
assert!(description.contains("test_op"));
assert!(description.contains("improving"));
assert!(description.contains("15.0%"));
assert!(description.contains("90%"));
}
#[test]
fn test_trend_significance() {
let significant_analysis = TrendAnalysis {
operation: "test".to_string(),
trend_direction: TrendDirection::Improving,
trend_strength: 0.8,
performance_change_percent: 25.0,
data_points: 5,
confidence: 0.9,
};
assert!(significant_analysis.is_significant(20.0, 0.8));
let insignificant_analysis = TrendAnalysis {
operation: "test".to_string(),
trend_direction: TrendDirection::Stable,
trend_strength: 0.2,
performance_change_percent: 5.0,
data_points: 3,
confidence: 0.5,
};
assert!(!insignificant_analysis.is_significant(20.0, 0.8));
}
#[test]
fn test_trend_directions() {
use TrendDirection::*;
assert_eq!(Improving, Improving);
assert_eq!(Declining, Declining);
assert_eq!(Stable, Stable);
assert_ne!(Improving, Declining);
}
}