diff --git a/tests/contest/contest/src/main.rs b/tests/contest/contest/src/main.rs index 9cabe35ae0..a9cb4a4e3a 100644 --- a/tests/contest/contest/src/main.rs +++ b/tests/contest/contest/src/main.rs @@ -5,6 +5,7 @@ use crate::tests::example::get_example_test; use crate::tests::hooks::get_hooks_tests; use crate::tests::hostname::get_hostname_test; use crate::tests::intel_rdt::get_intel_rdt_test; +use crate::tests::io_priority::get_io_priority_test; use crate::tests::lifecycle::{ContainerCreate, ContainerLifecycle}; use crate::tests::linux_ns_itype::get_ns_itype_tests; use crate::tests::mounts_recursive::get_mounts_recursive_test; @@ -103,6 +104,7 @@ fn main() -> Result<()> { let mounts_recursive = get_mounts_recursive_test(); let intel_rdt = get_intel_rdt_test(); let sysctl = get_sysctl_test(); + let io_p_test = get_io_priority_test(); tm.add_test_group(Box::new(cl)); tm.add_test_group(Box::new(cc)); @@ -123,7 +125,7 @@ fn main() -> Result<()> { tm.add_test_group(Box::new(mounts_recursive)); tm.add_test_group(Box::new(intel_rdt)); tm.add_test_group(Box::new(sysctl)); - + tm.add_test_group(Box::new(io_p_test)); tm.add_cleanup(Box::new(cgroups::cleanup_v1)); tm.add_cleanup(Box::new(cgroups::cleanup_v2)); diff --git a/tests/contest/contest/src/tests/io_priority/io_priority_test.rs b/tests/contest/contest/src/tests/io_priority/io_priority_test.rs new file mode 100644 index 0000000000..40790e81b2 --- /dev/null +++ b/tests/contest/contest/src/tests/io_priority/io_priority_test.rs @@ -0,0 +1,70 @@ +use crate::utils::test_inside_container; +use anyhow::{Context, Result}; +use oci_spec::runtime::{ + IOPriorityClass, LinuxIOPriorityBuilder, ProcessBuilder, Spec, SpecBuilder, +}; +use test_framework::{test_result, Test, TestGroup, TestResult}; + +fn create_spec(io_priority_class: IOPriorityClass, execute_test: &str) -> Result { + let io_p = LinuxIOPriorityBuilder::default() + .class(io_priority_class) + .priority(1) + .build() + .unwrap(); + SpecBuilder::default() + .process( + ProcessBuilder::default() + .args( + ["runtimetest", execute_test] + .iter() + .map(|s| s.to_string()) + .collect::>(), + ) + .io_priority(io_p) + .build()?, + ) + .build() + .context("failed to create spec") +} + +fn io_priority_class_rt_test() -> TestResult { + let spec = test_result!(create_spec( + IOPriorityClass::IoprioClassRt, + "io_priority_class_rt" + )); + test_inside_container(spec, &|_| Ok(())) +} + +fn io_priority_class_be_test() -> TestResult { + let spec = test_result!(create_spec( + IOPriorityClass::IoprioClassBe, + "io_priority_class_be" + )); + test_inside_container(spec, &|_| Ok(())) +} + +fn io_priority_class_idle_test() -> TestResult { + let spec = test_result!(create_spec( + IOPriorityClass::IoprioClassIdle, + "io_priority_class_idle" + )); + test_inside_container(spec, &|_| Ok(())) +} + +pub fn get_io_priority_test() -> TestGroup { + let mut io_priority_group = TestGroup::new("set_io_priority"); + let io_priority_class_rt = + Test::new("io_priority_class_rt", Box::new(io_priority_class_rt_test)); + let io_priority_class_be = + Test::new("io_priority_class_be", Box::new(io_priority_class_be_test)); + let io_priority_class_idle = Test::new( + "io_priority_class_idle", + Box::new(io_priority_class_idle_test), + ); + + io_priority_group.add(vec![Box::new(io_priority_class_rt)]); + io_priority_group.add(vec![Box::new(io_priority_class_be)]); + io_priority_group.add(vec![Box::new(io_priority_class_idle)]); + + io_priority_group +} diff --git a/tests/contest/contest/src/tests/io_priority/mod.rs b/tests/contest/contest/src/tests/io_priority/mod.rs new file mode 100644 index 0000000000..9d6849540a --- /dev/null +++ b/tests/contest/contest/src/tests/io_priority/mod.rs @@ -0,0 +1,3 @@ +mod io_priority_test; + +pub use io_priority_test::get_io_priority_test; diff --git a/tests/contest/contest/src/tests/mod.rs b/tests/contest/contest/src/tests/mod.rs index c0d738e226..6d12155ee3 100644 --- a/tests/contest/contest/src/tests/mod.rs +++ b/tests/contest/contest/src/tests/mod.rs @@ -3,6 +3,7 @@ pub mod example; pub mod hooks; pub mod hostname; pub mod intel_rdt; +pub mod io_priority; pub mod lifecycle; pub mod linux_ns_itype; pub mod mounts_recursive; diff --git a/tests/contest/runtimetest/src/main.rs b/tests/contest/runtimetest/src/main.rs index cbeb53a284..38a687d1b9 100644 --- a/tests/contest/runtimetest/src/main.rs +++ b/tests/contest/runtimetest/src/main.rs @@ -35,6 +35,9 @@ fn main() { "mounts_recursive" => tests::validate_mounts_recursive(&spec), "seccomp" => tests::validate_seccomp(&spec), "sysctl" => tests::validate_sysctl(&spec), + "io_priority_class_rt" => tests::test_io_priority_class_rt(&spec), + "io_priority_class_be" => tests::test_io_priority_class_be(&spec), + "io_priority_class_idle" => tests::test_io_priority_class_idle(&spec), _ => eprintln!("error due to unexpected execute test name: {execute_test}"), } } diff --git a/tests/contest/runtimetest/src/tests.rs b/tests/contest/runtimetest/src/tests.rs index 4275b8af7b..57bd28fa26 100644 --- a/tests/contest/runtimetest/src/tests.rs +++ b/tests/contest/runtimetest/src/tests.rs @@ -1,8 +1,12 @@ use crate::utils::{self, test_read_access, test_write_access}; use anyhow::{bail, Result}; use nix::errno::Errno; +use nix::libc; use nix::unistd::getcwd; -use oci_spec::runtime::Spec; +use oci_spec::runtime::{ + IOPriorityClass::{IoprioClassBe, IoprioClassIdle, IoprioClassRt}, + Spec, +}; use std::fs::{self, read_dir}; use std::path::Path; @@ -296,7 +300,9 @@ pub fn validate_sysctl(spec: &Spec) { .trim() .to_string(), Err(e) => { - return eprintln!("error due to fail to read the file {key_path:?}, error: {e}") + return eprintln!( + "error due to fail to read the file {key_path:?}, error: {e}" + ); } }; if &actual_value != expected_value { @@ -307,3 +313,117 @@ pub fn validate_sysctl(spec: &Spec) { } } } + +pub fn test_io_priority_class_rt(spec: &Spec) { + let io_p = spec + .process() + .as_ref() + .unwrap() + .io_priority() + .as_ref() + .unwrap(); + if io_p.class() != IoprioClassRt { + let io_class = io_p.class(); + return eprintln!("error io_priority class want {IoprioClassRt:?}, got {io_class:?}"); + } + // 1 is set test priority + if io_p.priority() != 1 { + let priority = io_p.priority(); + return eprintln!("error io_priority priority want 1, got {priority}"); + } + + let ioprio_who_progress: libc::c_int = 1; + let ioprio_who_pid = 0; + let res = unsafe { libc::syscall(libc::SYS_ioprio_get, ioprio_who_progress, ioprio_who_pid) }; + if let Err(e) = Errno::result(res) { + return eprintln!("error ioprio_get error {e}"); + } + + let class = res as u16 >> 13; + let priority = res as u16 & 0x1FFF; + // 1 is IoprioClassRt + if class != 1 { + return eprintln!("error ioprio_get class want {IoprioClassRt:?}, got {class}"); + } + + // because test case priority set value is 1 + if priority != 1 { + eprintln!("error ioprio_get priority want 1, got {priority}") + } +} + +pub fn test_io_priority_class_be(spec: &Spec) { + let io_p = spec + .process() + .as_ref() + .unwrap() + .io_priority() + .as_ref() + .unwrap(); + if io_p.class() != IoprioClassBe { + let io_class = io_p.class(); + return eprintln!("error io_priority class want {IoprioClassRt:?}, got {io_class:?}"); + } + // 1 is set test priority + if io_p.priority() != 1 { + let priority = io_p.priority(); + return eprintln!("error io_priority priority want 1, got {priority}"); + } + + let ioprio_who_progress: libc::c_int = 1; + let ioprio_who_pid = 0; + let res = unsafe { libc::syscall(libc::SYS_ioprio_get, ioprio_who_progress, ioprio_who_pid) }; + if let Err(e) = Errno::result(res) { + return eprintln!("error ioprio_get error {e}"); + } + + let class = res as u16 >> 13; + let priority = res as u16 & 0x1FFF; + // 2 is IoprioClassBe + if class != 2 { + return eprintln!("error ioprio_get class want {IoprioClassBe:?}, got {class}"); + } + + // because test case priority set value is 1 + if priority != 1 { + eprintln!("error ioprio_get priority want 1, got {priority}") + } +} + +pub fn test_io_priority_class_idle(spec: &Spec) { + let io_p = spec + .process() + .as_ref() + .unwrap() + .io_priority() + .as_ref() + .unwrap(); + if io_p.class() != IoprioClassIdle { + let io_class = io_p.class(); + return eprintln!("error io_priority class want {IoprioClassRt:?}, got {io_class:?}"); + } + // 1 is set test priority + if io_p.priority() != 1 { + let priority = io_p.priority(); + return eprintln!("error io_priority priority want 1, got {priority}"); + } + + let ioprio_who_progress: libc::c_int = 1; + let ioprio_who_pid = 0; + let res = unsafe { libc::syscall(libc::SYS_ioprio_get, ioprio_who_progress, ioprio_who_pid) }; + if let Err(e) = Errno::result(res) { + return eprintln!("error ioprio_get error {e}"); + } + + let class = res as u16 >> 13; + let priority = res as u16 & 0x1FFF; + // 3 is IoprioClassIdle + if class != 3 { + return eprintln!("error ioprio_get class want {IoprioClassIdle:?}, got {class}"); + } + + // because test case priority set value is 1 + if priority != 1 { + eprintln!("error ioprio_get priority want 1, got {priority}") + } +}