mirror of
https://github.com/containers/youki
synced 2024-11-23 09:21:57 +01:00
Cpu weight & quota tests
This commit is contained in:
parent
67bfc4c920
commit
90ba7e066a
@ -1,9 +1,301 @@
|
||||
use test_framework::TestGroup;
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
use crate::utils::{
|
||||
test_outside_container,
|
||||
test_utils::{check_container_created, CGROUP_ROOT},
|
||||
};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use libcgroups::{
|
||||
common::{self, CgroupSetup},
|
||||
v2::controller_type::ControllerType,
|
||||
};
|
||||
use log::debug;
|
||||
use oci_spec::runtime::LinuxCpuBuilder;
|
||||
use test_framework::{assert_result_eq, test_result, ConditionalTest, TestGroup, TestResult};
|
||||
|
||||
use super::create_spec;
|
||||
|
||||
// SPEC: The runtime spec does not specify what should happen if the cpu weight is outside
|
||||
// of the valid range of values [1, 10000]. We assume that a value of zero means that no action
|
||||
// should be taken and a value of over 10000 (after being converted into the cgroup v2 format)
|
||||
// should be set to the maximum value (i.e. 10000).
|
||||
// It also does not specify what should happen if the cpu quota or cpu period is negative or zero.
|
||||
// We assume that a negative value means that it should be set to the default value and zero means
|
||||
// that it should be unchanged.
|
||||
|
||||
/// Tests if a cpu weight that is in the valid range [1, 10000] is successfully set
|
||||
fn test_cpu_weight_valid_set() -> TestResult {
|
||||
let cpu_weight = 22_000u64;
|
||||
let converted_cpu_weight = 840u64;
|
||||
let cpu = test_result!(LinuxCpuBuilder::default()
|
||||
.shares(cpu_weight)
|
||||
.build()
|
||||
.context("build cpu spec"));
|
||||
|
||||
let spec = test_result!(create_spec("test_cpu_weight_valid_set", cpu));
|
||||
test_outside_container(spec, &|data| {
|
||||
test_result!(check_container_created(&data));
|
||||
test_result!(check_cpu_weight(
|
||||
"test_cpu_weight_valid_set",
|
||||
converted_cpu_weight
|
||||
));
|
||||
TestResult::Passed
|
||||
})
|
||||
}
|
||||
|
||||
/// Tests if a cpu weight of zero is ignored
|
||||
fn test_cpu_weight_zero_ignored() -> TestResult {
|
||||
let cpu_weight = 0u64;
|
||||
let default_cpu_weight = 100;
|
||||
let cpu = test_result!(LinuxCpuBuilder::default()
|
||||
.shares(cpu_weight)
|
||||
.build()
|
||||
.context("build cpu spec"));
|
||||
|
||||
let spec = test_result!(create_spec("test_cpu_weight_zero_ignored", cpu));
|
||||
test_outside_container(spec, &|data| {
|
||||
test_result!(check_container_created(&data));
|
||||
test_result!(check_cpu_weight(
|
||||
"test_cpu_weight_zero_ignored",
|
||||
default_cpu_weight
|
||||
));
|
||||
TestResult::Passed
|
||||
})
|
||||
}
|
||||
|
||||
/// Tests if a cpu weight that is too high (over 10000 after conversion) is set to the maximum value
|
||||
fn test_cpu_weight_too_high_maximum_set() -> TestResult {
|
||||
let cpu_weight = 500_000u64;
|
||||
let converted_cpu_weight = 10_000;
|
||||
let cpu = test_result!(LinuxCpuBuilder::default()
|
||||
.shares(cpu_weight)
|
||||
.build()
|
||||
.context("build cpu spec"));
|
||||
|
||||
let spec = test_result!(create_spec("test_cpu_weight_too_high_maximum_set", cpu));
|
||||
test_outside_container(spec, &|data| {
|
||||
test_result!(check_container_created(&data));
|
||||
test_result!(check_cpu_weight(
|
||||
"test_cpu_weight_too_high_maximum_set",
|
||||
converted_cpu_weight
|
||||
));
|
||||
TestResult::Passed
|
||||
})
|
||||
}
|
||||
|
||||
/// Tests if a valid cpu quota (x > 0) is set successfully
|
||||
fn test_cpu_quota_valid_set() -> TestResult {
|
||||
let cpu_quota = 250_000;
|
||||
let cpu = test_result!(LinuxCpuBuilder::default()
|
||||
.quota(cpu_quota)
|
||||
.build()
|
||||
.context("build cpu spec"));
|
||||
|
||||
let spec = test_result!(create_spec("test_cpu_quota_valid_set", cpu));
|
||||
test_outside_container(spec, &|data| {
|
||||
test_result!(check_container_created(&data));
|
||||
test_result!(check_cpu_quota("test_cpu_quota_valid_set", cpu_quota));
|
||||
TestResult::Passed
|
||||
})
|
||||
}
|
||||
|
||||
/// Tests if the cpu quota is unchanged if the cpu quota is unspecified (should be 'max')
|
||||
fn test_cpu_quota_unspecified_unchanged() -> TestResult {
|
||||
let cpu = test_result!(LinuxCpuBuilder::default()
|
||||
.build()
|
||||
.context("build cpu spec"));
|
||||
|
||||
let spec = test_result!(create_spec("test_cpu_quota_unspecified_unchanged", cpu));
|
||||
test_outside_container(spec, &|data| {
|
||||
test_result!(check_container_created(&data));
|
||||
test_result!(check_cpu_quota(
|
||||
"test_cpu_quota_unspecified_unchanged",
|
||||
i64::MAX
|
||||
));
|
||||
TestResult::Passed
|
||||
})
|
||||
}
|
||||
|
||||
/// Tests if the cpu quota is the default value (max) if a negative cpu quota has been specified
|
||||
fn test_cpu_quota_negative_value_default_set() -> TestResult {
|
||||
let cpu_quota = -9999;
|
||||
let cpu = test_result!(LinuxCpuBuilder::default()
|
||||
.quota(cpu_quota)
|
||||
.build()
|
||||
.context("build cpu spec"));
|
||||
|
||||
let spec = test_result!(create_spec(
|
||||
"test_cpu_quota_negative_value_default_set",
|
||||
cpu
|
||||
));
|
||||
test_outside_container(spec, &|data| {
|
||||
test_result!(check_container_created(&data));
|
||||
test_result!(check_cpu_quota(
|
||||
"test_cpu_quota_negative_value_default_set",
|
||||
i64::MAX
|
||||
));
|
||||
TestResult::Passed
|
||||
})
|
||||
}
|
||||
|
||||
/// Tests if a valid cpu period (x > 0) is set successfully
|
||||
fn test_cpu_period_valid_set() -> TestResult {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Tests if the cpu period is unchanged if the cpu period is unspecified
|
||||
fn test_cpu_period_unspecified_unchanged() -> TestResult {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Tests if the cpu period is the default value (100000) if a negative value has been specified
|
||||
fn test_cpu_period_negative_value_default_set() -> TestResult {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn check_cpu_weight(cgroup_name: &str, expected_weight: u64) -> Result<()> {
|
||||
let data = read_cgroup_data(cgroup_name, "cpu.weight")?;
|
||||
|
||||
let actual_weight = data
|
||||
.parse::<u64>()
|
||||
.with_context(|| format!("failed to parse {:?}", data))?;
|
||||
assert_result_eq!(actual_weight, expected_weight, "unexpected cpu weight")
|
||||
}
|
||||
|
||||
fn check_cpu_quota(cgroup_name: &str, expected_quota: i64) -> Result<()> {
|
||||
let data = read_cgroup_data(cgroup_name, "cpu.max")?;
|
||||
let parts: Vec<&str> = data.split_whitespace().collect();
|
||||
if parts.len() != 2 {
|
||||
bail!(
|
||||
"expected cpu.max to consist of 'quota period' but was {:?}",
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
let quota = parts[0].trim();
|
||||
if expected_quota == i64::MAX {
|
||||
if quota == "max" {
|
||||
return Ok(());
|
||||
} else {
|
||||
bail!("expected cpu quota to be 'max', but was {:?}", quota);
|
||||
}
|
||||
}
|
||||
|
||||
let actual_quota = quota
|
||||
.parse::<i64>()
|
||||
.with_context(|| format!("failed to parse {:?}", quota))?;
|
||||
assert_result_eq!(expected_quota, actual_quota, "unexpected cpu quota");
|
||||
}
|
||||
|
||||
fn read_cgroup_data(cgroup_name: &str, cgroup_file: &str) -> Result<String> {
|
||||
let cgroup_path = PathBuf::from(CGROUP_ROOT)
|
||||
.join("runtime-test")
|
||||
.join(cgroup_name)
|
||||
.join(cgroup_file);
|
||||
|
||||
log::debug!("reading value from {:?}", cgroup_path);
|
||||
let content = fs::read_to_string(&cgroup_path)
|
||||
.with_context(|| format!("failed to read {:?}", cgroup_path))?;
|
||||
let trimmed = content.trim();
|
||||
Ok(trimmed.to_owned())
|
||||
}
|
||||
|
||||
fn can_run() -> bool {
|
||||
todo!();
|
||||
let setup_result = common::get_cgroup_setup();
|
||||
if !matches!(setup_result, Ok(CgroupSetup::Unified)) {
|
||||
debug!("cgroup setup is not v2, was {:?}", setup_result);
|
||||
return false;
|
||||
}
|
||||
|
||||
let controllers_result =
|
||||
libcgroups::v2::util::get_available_controllers(common::DEFAULT_CGROUP_ROOT);
|
||||
if controllers_result.is_err() {
|
||||
debug!(
|
||||
"could not retrieve cgroup controllers: {:?}",
|
||||
controllers_result
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if controllers_result
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.find(|c| *c == ControllerType::Cpu)
|
||||
.is_none()
|
||||
{
|
||||
debug!("cpu controller is not attached to the v2 hierarchy");
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
pub fn get_test_group<'a>() -> TestGroup<'a> {
|
||||
todo!()
|
||||
}
|
||||
let mut test_group = TestGroup::new("cgroup_v2_cpu");
|
||||
let test_cpu_weight_valid_set = ConditionalTest::new(
|
||||
"test_cpu_weight_valid_set",
|
||||
Box::new(can_run),
|
||||
Box::new(test_cpu_weight_valid_set),
|
||||
);
|
||||
|
||||
let test_cpu_weight_zero_ignored = ConditionalTest::new(
|
||||
"test_cpu_weight_zero_ignored",
|
||||
Box::new(can_run),
|
||||
Box::new(test_cpu_weight_zero_ignored),
|
||||
);
|
||||
|
||||
let test_cpu_weight_too_high_maximum_set = ConditionalTest::new(
|
||||
"test_cpu_weight_too_high_maximum_set",
|
||||
Box::new(can_run),
|
||||
Box::new(test_cpu_weight_too_high_maximum_set),
|
||||
);
|
||||
|
||||
let test_cpu_quota_valid_set = ConditionalTest::new(
|
||||
"test_cpu_quota_valid_set",
|
||||
Box::new(can_run),
|
||||
Box::new(test_cpu_quota_valid_set),
|
||||
);
|
||||
|
||||
let test_cpu_quota_unspecified_unchanged = ConditionalTest::new(
|
||||
"test_cpu_quota_unspecified_unchanged",
|
||||
Box::new(can_run),
|
||||
Box::new(test_cpu_quota_unspecified_unchanged),
|
||||
);
|
||||
|
||||
let test_cpu_quota_negative_value_default_set = ConditionalTest::new(
|
||||
"test_cpu_quota_negative_value_default_set",
|
||||
Box::new(can_run),
|
||||
Box::new(test_cpu_quota_negative_value_default_set),
|
||||
);
|
||||
|
||||
let test_cpu_period_valid_set = ConditionalTest::new(
|
||||
"test_cpu_period_valid_set",
|
||||
Box::new(can_run),
|
||||
Box::new(test_cpu_period_valid_set),
|
||||
);
|
||||
|
||||
let test_cpu_period_unspecified_unchanged = ConditionalTest::new(
|
||||
"test_cpu_period_unspecified_unchanged",
|
||||
Box::new(can_run),
|
||||
Box::new(test_cpu_period_unspecified_unchanged),
|
||||
);
|
||||
|
||||
let test_cpu_period_negative_value_default_set = ConditionalTest::new(
|
||||
"test_cpu_period_negative_value_default_set",
|
||||
Box::new(can_run),
|
||||
Box::new(test_cpu_period_negative_value_default_set),
|
||||
);
|
||||
|
||||
test_group.add(vec![
|
||||
Box::new(test_cpu_weight_valid_set),
|
||||
Box::new(test_cpu_weight_zero_ignored),
|
||||
Box::new(test_cpu_weight_too_high_maximum_set),
|
||||
Box::new(test_cpu_quota_valid_set),
|
||||
Box::new(test_cpu_quota_unspecified_unchanged),
|
||||
Box::new(test_cpu_quota_negative_value_default_set),
|
||||
// Box::new(test_cpu_period_valid_set),
|
||||
// Box::new(test_cpu_period_unspecified_unchanged),
|
||||
// Box::new(test_cpu_period_negative_value_default_set),
|
||||
]);
|
||||
test_group
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user