updated safety measurements and benchmarking behavior for 9380

This commit is contained in:
2026-02-28 18:55:18 +01:00
parent 1702e7d058
commit 8d351c7bde
10 changed files with 329 additions and 334 deletions

View File

@@ -1,35 +1,75 @@
#[path = "../src/engine/formatters/throttled.rs"]
mod throttled;
use throttled::{ThrottledTranslator, ThrottledConfig};
use ember_tune_rs::engine::formatters::throttled::{ThrottledConfig, ThrottledTranslator};
use ember_tune_rs::agent_analyst::{OptimizationMatrix, SystemProfile, FanCurvePoint};
use ember_tune_rs::agent_integrator::ServiceIntegrator;
use std::fs;
use tempfile::tempdir;
#[test]
fn test_throttled_formatter_non_destructive() {
let fixture_path = "tests/fixtures/throttled.conf";
let existing_content = fs::read_to_string(fixture_path).expect("Failed to read fixture");
fn test_throttled_merge_preserves_undervolt() {
let existing = r#"[GENERAL]
Update_Interval_ms: 1000
[UNDERVOLT]
# CPU core undervolt
CORE: -100
# GPU undervolt
GPU: -50
[AC]
PL1_Tdp_W: 15
PL2_Tdp_W: 25
"#;
let config = ThrottledConfig {
pl1_limit: 25.0,
pl2_limit: 35.0,
trip_temp: 90.0,
pl1_limit: 22.0,
pl2_limit: 28.0,
trip_temp: 95.0,
};
let merged = ThrottledTranslator::merge_conf(&existing_content, &config);
let merged = ThrottledTranslator::merge_conf(existing, &config);
// Assert updates
assert!(merged.contains("PL1_Tdp_W: 25"));
assert!(merged.contains("PL2_Tdp_W: 35"));
assert!(merged.contains("Trip_Temp_C: 90"));
// Assert preservation
assert!(merged.contains("[UNDERVOLT]"));
assert!(merged.contains("CORE: -100"));
assert!(merged.contains("GPU: -50"));
assert!(merged.contains("# Important: Preserving undervolt offsets is critical!"));
assert!(merged.contains("Update_Interval_ms: 3000"));
// Check that we didn't lose the [GENERAL] section
assert!(merged.contains("[GENERAL]"));
assert!(merged.contains("# This is a complex test fixture"));
assert!(merged.contains("PL1_Tdp_W: 22"));
assert!(merged.contains("PL2_Tdp_W: 28"));
assert!(merged.contains("Trip_Temp_C: 95"));
assert!(merged.contains("[UNDERVOLT]"));
}
#[test]
fn test_i8kmon_merge_preserves_settings() {
let dir = tempdir().unwrap();
let config_path = dir.path().join("i8kmon.conf");
let existing = r#"set config(gen_shadow) 1
set config(i8k_ignore_dmi) 1
set config(daemon) 1
set config(0) {0 0 60 50}
"#;
fs::write(&config_path, existing).unwrap();
let matrix = OptimizationMatrix {
silent: SystemProfile { name: "Silent".to_string(), pl1_watts: 10.0, pl2_watts: 12.0, fan_curve: vec![] },
balanced: SystemProfile {
name: "Balanced".to_string(),
pl1_watts: 20.0,
pl2_watts: 25.0,
fan_curve: vec![
FanCurvePoint { temp_on: 70.0, temp_off: 60.0, pwm_percent: 50 }
]
},
performance: SystemProfile { name: "Perf".to_string(), pl1_watts: 30.0, pl2_watts: 35.0, fan_curve: vec![] },
thermal_resistance_kw: 1.5,
ambient_temp: 25.0,
};
ServiceIntegrator::generate_i8kmon_config(&matrix, &config_path, Some(&config_path)).unwrap();
let result = fs::read_to_string(&config_path).unwrap();
assert!(result.contains("set config(gen_shadow) 1"));
assert!(result.contains("set config(daemon) 1"));
assert!(result.contains("set config(0) {1 1 70 -}")); // New config
assert!(!result.contains("set config(0) {0 0 60 50}")); // Old config should be gone
}

View File

@@ -1,8 +1,6 @@
use anyhow::Result;
use std::fs;
use std::path::PathBuf;
use ember_tune_rs::sal::safety::{HardwareStateGuard, TdpLimitMicroWatts};
use ember_tune_rs::sal::safety::{HardwareStateGuard, PowerLimitWatts};
use crate::common::fakesys::FakeSysBuilder;
use std::fs;
mod common;
@@ -34,23 +32,22 @@ fn test_hardware_state_guard_panic_restoration() {
#[test]
fn test_tdp_limit_bounds_checking() {
// 1. Valid value
assert!(TdpLimitMicroWatts::new(15_000_000).is_ok());
assert!(PowerLimitWatts::try_new(15.0).is_ok());
// 2. Too low (Dangerous 0W or below 5W)
let low_res = TdpLimitMicroWatts::new(1_000_000);
// 2. Too low (Dangerous 0W or below 3W)
let low_res = PowerLimitWatts::try_new(1.0);
assert!(low_res.is_err());
assert!(low_res.unwrap_err().to_string().contains("below safety floor"));
assert!(low_res.unwrap_err().to_string().contains("outside safe bounds"));
// 3. Too high (> 80W)
let high_res = TdpLimitMicroWatts::new(100_000_000);
// 3. Too high (> 100W)
let high_res = PowerLimitWatts::try_new(150.0);
assert!(high_res.is_err());
assert!(high_res.unwrap_err().to_string().contains("exceeds safety ceiling"));
assert!(high_res.unwrap_err().to_string().contains("outside safe bounds"));
}
#[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);
let zero_res = PowerLimitWatts::try_new(0.0);
assert!(zero_res.is_err());
}