blob: eee048ee39606ec02071991040f1034216d21f11 [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#[cfg(test)]
pub(crate) mod tests {
use anyhow::Result;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::str;
use crate::common::{FullscreenVideo, GameMode, RTCAudioActive, VmBootMode};
use crate::power;
const MOCK_NUM_CPU: i32 = 16;
pub const CPUINFO_PATH: &str = "proc/cpuinfo";
/// Base path for power_limit relative to rootdir.
pub const DEVICE_POWER_LIMIT_PATH: &str = "sys/class/powercap/intel-rapl:0";
/// Base path for cpufreq relative to rootdir.
pub const DEVICE_CPUFREQ_PATH: &str = "sys/devices/system/cpu/cpufreq";
// Device path for GPU card.
pub const GPU0_DEVICE_PATH: &str = "sys/class/drm/card0";
pub struct MockPowerPreferencesManager {}
impl power::PowerPreferencesManager for MockPowerPreferencesManager {
fn update_power_preferences(
&self,
_rtc: RTCAudioActive,
_fullscreen: FullscreenVideo,
_game: GameMode,
_vmboot: VmBootMode,
) -> Result<()> {
Ok(())
}
}
pub fn write_mock_pl0(root: &Path, value: u64) -> Result<()> {
std::fs::write(
root.join(DEVICE_POWER_LIMIT_PATH)
.join("constraint_0_power_limit_uw"),
value.to_string(),
)?;
Ok(())
}
pub fn write_mock_cpu(
root: &Path,
cpu_num: i32,
baseline_max: u64,
curr_max: u64,
baseline_min: u64,
curr_min: u64,
) -> Result<()> {
let policy_path = root
.join(DEVICE_CPUFREQ_PATH)
.join(format!("policy{cpu_num}"));
std::fs::write(
policy_path.join("cpuinfo_max_freq"),
baseline_max.to_string(),
)
.expect("Failed to write to file!");
std::fs::write(
policy_path.join("cpuinfo_min_freq"),
baseline_min.to_string(),
)
.expect("Failed to write to file!");
std::fs::write(policy_path.join("scaling_max_freq"), curr_max.to_string())?;
std::fs::write(policy_path.join("scaling_min_freq"), curr_min.to_string())?;
Ok(())
}
pub fn setup_mock_cpu_dev_dirs(root: &Path) -> anyhow::Result<()> {
fs::create_dir_all(root.join(DEVICE_POWER_LIMIT_PATH))?;
for i in 0..MOCK_NUM_CPU {
fs::create_dir_all(root.join(DEVICE_CPUFREQ_PATH).join(format!("policy{i}")))?;
}
Ok(())
}
pub fn get_cpu0_freq_max(root: &Path) -> i32 {
let policy_path = root.join(DEVICE_CPUFREQ_PATH).join("policy0");
let read_val = std::fs::read(policy_path.join("scaling_max_freq")).unwrap();
std::str::from_utf8(&read_val)
.unwrap()
.parse::<i32>()
.unwrap()
}
pub fn get_cpu0_freq_min(root: &Path) -> i32 {
let policy_path = root.join(DEVICE_CPUFREQ_PATH).join("policy0");
let read_val = std::fs::read(policy_path.join("scaling_min_freq")).unwrap();
str::from_utf8(&read_val).unwrap().parse::<i32>().unwrap()
}
pub fn setup_mock_cpu_files(root: &Path) -> Result<()> {
let pl_files: Vec<&str> = vec![
"constraint_0_power_limit_uw",
"constraint_0_max_power_uw",
"constraint_1_power_limit_uw",
"constraint_1_max_power_uw",
"energy_uj",
"max_energy_range_uj",
];
let cpufreq_files: Vec<(&str, &str)> = vec![
("scaling_max_freq", "4100000"),
("cpuinfo_max_freq", "4100000"),
("scaling_min_freq", "400000"),
("cpuinfo_min_freq", "400000"),
("base_frequency", "2100000"),
];
for pl_file in &pl_files {
std::fs::write(
root.join(DEVICE_POWER_LIMIT_PATH)
.join(PathBuf::from(pl_file)),
"0",
)?;
}
for i in 0..MOCK_NUM_CPU {
let policy_path = root.join(DEVICE_CPUFREQ_PATH).join(format!("policy{i}"));
for cpufreq_file in &cpufreq_files {
std::fs::write(policy_path.join(cpufreq_file.0), cpufreq_file.1)?;
}
}
Ok(())
}
pub fn construct_poc_cpuinfo_snippet(vendor: &str, model_name: &str) -> String {
format!(
r#"
processor : 0
vendor_id : {vendor}
cpu family : 23
model : 24
model name : {model_name}
stepping : 1
microcode : 0x8108109
processor : 1
vendor_id : {vendor}
cpu family : 25
model : 24
model name : {model_name}"#
)
}
pub fn write_mock_cpuinfo(root: &Path, vendor: &str, model_name: &str) {
fs::write(
root.join(CPUINFO_PATH),
construct_poc_cpuinfo_snippet(vendor, model_name),
)
.unwrap();
}
pub fn setup_mock_intel_gpu_dev_dirs(root: &Path) {
fs::create_dir_all(root.join(CPUINFO_PATH).parent().unwrap()).unwrap();
fs::create_dir_all(root.join(GPU0_DEVICE_PATH)).unwrap();
}
pub fn setup_mock_intel_gpu_files(root: &Path) {
let gpu_files = vec![
("gt_min_freq_mhz", 200),
("gt_max_freq_mhz", 1000),
("gt_boost_freq_mhz", 1000),
];
for (gpu_file, default_freq) in &gpu_files {
fs::write(
root.join(GPU0_DEVICE_PATH).join(PathBuf::from(gpu_file)),
default_freq.to_string(),
)
.unwrap();
}
}
pub fn get_intel_gpu_max(root: &Path) -> i32 {
let gpu_max_path = root.join(GPU0_DEVICE_PATH).join("gt_max_freq_mhz");
let read_val = std::fs::read(gpu_max_path).unwrap();
str::from_utf8(&read_val).unwrap().parse::<i32>().unwrap()
}
pub fn get_intel_gpu_boost(root: &Path) -> i32 {
let gpu_max_path = root.join(GPU0_DEVICE_PATH).join("gt_boost_freq_mhz");
let read_val = std::fs::read(gpu_max_path).unwrap();
str::from_utf8(&read_val).unwrap().parse::<i32>().unwrap()
}
}