use anyhow::Result; use std::fs; use std::path::PathBuf; use ember_tune_rs::sal::safety::{HardwareStateGuard, TdpLimitMicroWatts}; use crate::common::fakesys::FakeSysBuilder; mod common; #[test] fn test_hardware_state_guard_panic_restoration() { let fake = FakeSysBuilder::new(); let pl1_path = fake.base_path().join("sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw"); fake.add_rapl("intel-rapl:0", "1000", "15000000"); // 15W original let target_files = vec![pl1_path.clone()]; // Simulate a scope where the guard is active { let mut _guard = HardwareStateGuard::acquire(&target_files, &[]).expect("Failed to acquire guard"); // Modify the file fs::write(&pl1_path, "25000000").expect("Failed to write new value"); assert_eq!(fs::read_to_string(&pl1_path).unwrap().trim(), "25000000"); // Guard is dropped here (simulating end of scope or panic) } // Verify restoration let restored = fs::read_to_string(&pl1_path).expect("Failed to read restored file"); assert_eq!(restored.trim(), "15000000"); } #[test] fn test_tdp_limit_bounds_checking() { // 1. Valid value assert!(TdpLimitMicroWatts::new(15_000_000).is_ok()); // 2. Too low (Dangerous 0W or below 5W) let low_res = TdpLimitMicroWatts::new(1_000_000); assert!(low_res.is_err()); assert!(low_res.unwrap_err().to_string().contains("below safety floor")); // 3. Too high (> 80W) let high_res = TdpLimitMicroWatts::new(100_000_000); assert!(high_res.is_err()); assert!(high_res.unwrap_err().to_string().contains("exceeds safety ceiling")); } #[test] fn test_0w_tdp_regression_prevention() { // The prime directive is to never set 0W. // Ensure the new() constructor explicitly fails for 0. let zero_res = TdpLimitMicroWatts::new(0); assert!(zero_res.is_err()); }