#![allow( clippy::assertions_on_constants, clippy::assertions_on_result_states, clippy::clone_on_copy, clippy::decimal_literal_representation, clippy::doc_markdown, clippy::empty_line_after_doc_comments, clippy::field_reassign_with_default, clippy::get_unwrap, clippy::identity_op, clippy::inconsistent_digit_grouping, clippy::indexing_slicing, clippy::integer_division, clippy::len_zero, clippy::let_underscore_must_use, clippy::manual_div_ceil, clippy::manual_let_else, clippy::manual_range_contains, clippy::modulo_arithmetic, clippy::needless_range_loop, clippy::non_ascii_literal, clippy::redundant_clone, clippy::shadow_reuse, clippy::shadow_same, clippy::shadow_unrelated, clippy::single_match_else, clippy::str_to_string, clippy::string_slice, clippy::tests_outside_test_module, clippy::too_many_lines, clippy::unnecessary_wraps, clippy::unseparated_literal_suffix, clippy::use_debug, clippy::useless_vec, clippy::wildcard_enum_match_arm, clippy::else_if_without_else, clippy::expect_used, clippy::missing_const_for_fn, clippy::similar_names, clippy::type_complexity, clippy::collapsible_else_if, clippy::doc_lazy_continuation, clippy::items_after_test_module, clippy::map_clone, clippy::multiple_unsafe_ops_per_block, clippy::unwrap_or_default, clippy::assign_op_pattern, clippy::needless_borrow, clippy::println_empty_string, clippy::unnecessary_cast, clippy::used_underscore_binding, clippy::create_dir, clippy::implicit_saturating_sub, clippy::exit, clippy::expect_fun_call, clippy::too_many_arguments, clippy::unnecessary_map_or, clippy::unwrap_used, dead_code, unused_imports, unused_variables, clippy::cloned_ref_to_slice_refs, clippy::neg_multiply, clippy::while_let_loop, clippy::bool_assert_comparison, clippy::excessive_precision, clippy::trivially_copy_pass_by_ref, clippy::op_ref, clippy::redundant_closure, clippy::unnecessary_lazy_evaluations, clippy::if_then_some_else_none, clippy::unnecessary_to_owned, clippy::single_component_path_imports, )] /// Wave 16M: Test log size reduction from 2.8MB → <1MB /// /// Validates that 1-epoch training produces <100KB of INFO-level logs /// (scaling to <1MB for 10 epochs). /// /// **Test Strategy**: /// 1. Run 1-epoch training with RUST_LOG=info /// 2. Capture log output to file /// 3. Verify file size <100KB (10x scaling → <1MB for 10 epochs) /// 4. Verify essential metrics still visible (epoch summary, trading stats) use std::fs::File; use std::io::Write; use std::process::Command; use tracing::info; #[test] fn test_log_size_under_1mb() { // Create temp log file let log_file = "/tmp/test_log_size.log"; // Run 1-epoch training with INFO-level logging let output = Command::new("cargo") .args(&[ "run", "-p", "ml", "--example", "train_baseline_rl", "--release", "--features", "cuda", "--", "--model", "dqn", "--epochs", "1", ]) .env("RUST_LOG", "info") .output() .expect("Failed to run training"); // Write output to file let mut file = File::create(log_file).expect("Failed to create log file"); file.write_all(&output.stdout).expect("Failed to write stdout"); file.write_all(&output.stderr).expect("Failed to write stderr"); // Check log size let metadata = std::fs::metadata(log_file).expect("Failed to read log file"); let size_bytes = metadata.len(); let size_kb = size_bytes as f64 / 1_024.0; let size_mb = size_bytes as f64 / 1_048_576.0; info!(size_kb, size_mb, "Log size"); // 1 epoch should produce <100KB (10 epochs → <1MB) assert!( size_kb < 100.0, "1-epoch log should be <100KB, got {:.2}KB ({:.3}MB). 10-epoch projection: {:.2}MB", size_kb, size_mb, size_mb * 10.0 ); // Verify essential metrics are still present (INFO level) let log_content = std::fs::read_to_string(log_file).expect("Failed to read log file"); // Essential metrics that MUST be visible at INFO level assert!( log_content.contains("Epoch 1/1"), "Missing epoch summary in INFO logs" ); assert!( log_content.contains("train_loss=") || log_content.contains("Training Stats"), "Missing training loss in INFO logs" ); assert!( log_content.contains("Trading Stats") || log_content.contains("P&L"), "Missing trading stats in INFO logs" ); assert!( log_content.contains("Action diversity") || log_content.contains("diversity="), "Missing action diversity in INFO logs" ); info!(size_kb, projected_10epoch_mb = size_mb * 10.0, "Test passed: log size within target"); } #[test] fn test_debug_logs_available() { // Create temp log file let log_file = "/tmp/test_log_debug.log"; // Run 1-epoch training with DEBUG-level logging let output = Command::new("cargo") .args(&[ "run", "-p", "ml", "--example", "train_baseline_rl", "--release", "--features", "cuda", "--", "--model", "dqn", "--epochs", "1", ]) .env("RUST_LOG", "debug") .output() .expect("Failed to run training"); // Write output to file let mut file = File::create(log_file).expect("Failed to create log file"); file.write_all(&output.stdout).expect("Failed to write stdout"); file.write_all(&output.stderr).expect("Failed to write stderr"); // Verify DEBUG logs contain step-level details let log_content = std::fs::read_to_string(log_file).expect("Failed to read log file"); // DEBUG-level details should be present assert!( log_content.contains("Q-values:") || log_content.contains("Diagnostics:"), "Missing step-level diagnostics in DEBUG logs" ); info!("DEBUG logs contain step-level details"); }