impemented mock testing
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
use anyhow::{Result, anyhow};
|
||||
use std::path::Path;
|
||||
use std::path::{Path};
|
||||
use std::fs;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::process::Command;
|
||||
use tracing::{debug, warn};
|
||||
use std::sync::Mutex;
|
||||
use tracing::{debug};
|
||||
|
||||
use crate::sal::traits::{SensorBus, ActuatorBus, EnvironmentGuard, HardwareWatchdog, PreflightAuditor, AuditStep, AuditError, SafetyStatus};
|
||||
use crate::sal::traits::{SensorBus, ActuatorBus, EnvironmentGuard, HardwareWatchdog, PreflightAuditor, AuditStep, AuditError, SafetyStatus, EnvironmentCtx};
|
||||
use crate::sal::heuristic::discovery::SystemFactSheet;
|
||||
use crate::sal::heuristic::schema::HardwareDb;
|
||||
|
||||
pub struct GenericLinuxSal {
|
||||
ctx: EnvironmentCtx,
|
||||
fact_sheet: SystemFactSheet,
|
||||
db: HardwareDb,
|
||||
suppressed_services: Mutex<Vec<String>>,
|
||||
@@ -20,14 +20,21 @@ pub struct GenericLinuxSal {
|
||||
}
|
||||
|
||||
impl GenericLinuxSal {
|
||||
pub fn new(facts: SystemFactSheet, db: HardwareDb) -> Self {
|
||||
pub fn new(ctx: EnvironmentCtx, facts: SystemFactSheet, db: HardwareDb) -> Self {
|
||||
let initial_energy = if let Some(pwr_base) = facts.rapl_paths.first() {
|
||||
fs::read_to_string(pwr_base.join("energy_uj")).unwrap_or_default().trim().parse().unwrap_or(0)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
Self {
|
||||
db,
|
||||
suppressed_services: Mutex::new(Vec::new()),
|
||||
last_valid_temp: Mutex::new((0.0, Instant::now())),
|
||||
current_pl1: Mutex::new(15.0),
|
||||
last_energy: Mutex::new((0, Instant::now())),
|
||||
last_energy: Mutex::new((initial_energy, Instant::now())),
|
||||
fact_sheet: facts,
|
||||
ctx,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +42,6 @@ impl GenericLinuxSal {
|
||||
self.fact_sheet.vendor.to_lowercase().contains("dell")
|
||||
}
|
||||
|
||||
/// Read sysfs safely. We removed the thread-per-read timeout logic
|
||||
/// as it was inefficient. sysfs reads are generally fast enough.
|
||||
fn read_sysfs(&self, path: &Path) -> Result<String> {
|
||||
fs::read_to_string(path).map(|s| s.trim().to_string()).map_err(|e| anyhow!(e))
|
||||
}
|
||||
@@ -46,11 +51,11 @@ impl PreflightAuditor for GenericLinuxSal {
|
||||
fn audit(&self) -> Box<dyn Iterator<Item = AuditStep> + '_> {
|
||||
let mut steps = Vec::new();
|
||||
for check in &self.db.preflight_checks {
|
||||
let status = Command::new("sh").arg("-c").arg(&check.check_cmd).status();
|
||||
let status = self.ctx.runner.run("sh", &["-c", &check.check_cmd]);
|
||||
steps.push(AuditStep {
|
||||
description: check.name.clone(),
|
||||
outcome: match status {
|
||||
Ok(s) if s.success() => Ok(()),
|
||||
Ok(_) => Ok(()),
|
||||
_ => Err(AuditError::KernelIncompatible(check.fail_help.clone())),
|
||||
}
|
||||
});
|
||||
@@ -106,11 +111,12 @@ impl SensorBus for GenericLinuxSal {
|
||||
}
|
||||
|
||||
fn get_freq_mhz(&self) -> Result<f32> {
|
||||
let path = Path::new("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq");
|
||||
let path = self.ctx.sysfs_base.join("sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq");
|
||||
if path.exists() {
|
||||
Ok(self.read_sysfs(path)?.parse::<f32>()? / 1000.0)
|
||||
Ok(self.read_sysfs(&path)?.parse::<f32>()? / 1000.0)
|
||||
} else {
|
||||
let cpuinfo = fs::read_to_string("/proc/cpuinfo")?;
|
||||
let cpuinfo_path = self.ctx.sysfs_base.join("proc/cpuinfo");
|
||||
let cpuinfo = fs::read_to_string(cpuinfo_path)?;
|
||||
for line in cpuinfo.lines() {
|
||||
if line.starts_with("cpu MHz") {
|
||||
if let Some((_, mhz)) = line.split_once(':') {
|
||||
@@ -133,7 +139,7 @@ impl ActuatorBus for GenericLinuxSal {
|
||||
};
|
||||
if let Some(cmd_str) = cmd {
|
||||
let parts: Vec<&str> = cmd_str.split_whitespace().collect();
|
||||
Command::new(parts[0]).args(&parts[1..]).status()?;
|
||||
self.ctx.runner.run(parts[0], &parts[1..])?;
|
||||
Ok(())
|
||||
} else { Err(anyhow!("Dell fan command missing")) }
|
||||
} else { Ok(()) }
|
||||
@@ -159,7 +165,8 @@ impl EnvironmentGuard for GenericLinuxSal {
|
||||
for conflict_id in &self.fact_sheet.active_conflicts {
|
||||
if let Some(conflict) = self.db.conflicts.iter().find(|c| &c.id == conflict_id) {
|
||||
for service in &conflict.services {
|
||||
if Command::new("systemctl").arg("stop").arg(service).status()?.success() {
|
||||
if self.ctx.runner.run("systemctl", &["is-active", "--quiet", service]).is_ok() {
|
||||
self.ctx.runner.run("systemctl", &["stop", service])?;
|
||||
suppressed.push(service.clone());
|
||||
}
|
||||
}
|
||||
@@ -171,7 +178,7 @@ impl EnvironmentGuard for GenericLinuxSal {
|
||||
fn restore(&self) -> Result<()> {
|
||||
let mut suppressed = self.suppressed_services.lock().unwrap();
|
||||
for service in suppressed.drain(..) {
|
||||
let _ = Command::new("systemctl").arg("start").arg(service).status();
|
||||
let _ = self.ctx.runner.run("systemctl", &["start", &service]);
|
||||
}
|
||||
if self.is_dell() { let _ = self.set_fan_mode("auto"); }
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user