Skip to content

Commit

Permalink
Add linux_devices test
Browse files Browse the repository at this point in the history
Signed-off-by: omprakaash <omsuseela@gmail.com>
Signed-off-by: om prakaash <omsuseela@gmail.com>
  • Loading branch information
omprakaash committed Apr 20, 2024
1 parent 7fa84ec commit 6f7eaec
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 0 deletions.
3 changes: 3 additions & 0 deletions tests/contest/contest/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod tests;
mod utils;

use crate::tests::devices::get_devices_test;
use crate::tests::domainname::get_domainname_tests;
use crate::tests::example::get_example_test;
use crate::tests::hooks::get_hooks_tests;
Expand Down Expand Up @@ -109,6 +110,7 @@ fn main() -> Result<()> {
let sysctl = get_sysctl_test();
let scheduler = get_scheduler_test();
let io_priority_test = get_io_priority_test();
let devices = get_devices_test();

tm.add_test_group(Box::new(cl));
tm.add_test_group(Box::new(cc));
Expand All @@ -131,6 +133,7 @@ fn main() -> Result<()> {
tm.add_test_group(Box::new(intel_rdt));
tm.add_test_group(Box::new(sysctl));
tm.add_test_group(Box::new(scheduler));
tm.add_test_group(Box::new(devices));

tm.add_test_group(Box::new(io_priority_test));
tm.add_cleanup(Box::new(cgroups::cleanup_v1));
Expand Down
71 changes: 71 additions & 0 deletions tests/contest/contest/src/tests/devices/devices_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use crate::utils::test_inside_container;
use anyhow::{Context, Ok, Result};
use oci_spec::runtime::{
LinuxBuilder, LinuxDeviceBuilder, LinuxDeviceType, ProcessBuilder, Spec, SpecBuilder,
};
use test_framework::{test_result, Test, TestGroup, TestResult};

fn create_spec() -> Result<Spec> {
let device1 = LinuxDeviceBuilder::default()
.path("/dev/test1")
.typ(LinuxDeviceType::C)
.major(10)
.minor(666)
.file_mode(432u32)
.uid(0u32)
.gid(0u32)
.build()
.context("failed to create device 1")?;

let device2 = LinuxDeviceBuilder::default()
.path("/dev/test2")
.typ(LinuxDeviceType::B)
.major(8)
.minor(666)
.file_mode(432u32)
.uid(0u32)
.gid(0u32)
.build()
.context("failed to create device 2")?;

let device3 = LinuxDeviceBuilder::default()
.path("/dev/test3")
.typ(LinuxDeviceType::P)
.major(8)
.minor(666)
.file_mode(432u32)
.build()
.context("failed to create device 3")?;

let spec = SpecBuilder::default()
.process(
ProcessBuilder::default()
.args(vec!["runtimetest".to_string(), "devices".to_string()])
.build()
.expect("error in creating process config"),
)
.linux(
LinuxBuilder::default()
.devices(vec![device1, device2, device3])
.build()
.context("failed to build linux spec")?,
)
.build()
.context("failed to build spec")?;

Ok(spec)
}

fn devices_test() -> TestResult {
let spec = test_result!(create_spec());
test_inside_container(spec, &|_| Ok(()))
}

pub fn get_devices_test() -> TestGroup {
let mut device_test_group = TestGroup::new("devices");

let test = Test::new("device_test", Box::new(devices_test));
device_test_group.add(vec![Box::new(test)]);

device_test_group
}
2 changes: 2 additions & 0 deletions tests/contest/contest/src/tests/devices/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod devices_test;
pub use devices_test::get_devices_test;
1 change: 1 addition & 0 deletions tests/contest/contest/src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod cgroups;
pub mod devices;
pub mod domainname;
pub mod example;
pub mod hooks;
Expand Down
1 change: 1 addition & 0 deletions tests/contest/runtimetest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ fn main() {
"io_priority_class_rt" => tests::test_io_priority_class(&spec, IoprioClassRt),
"io_priority_class_be" => tests::test_io_priority_class(&spec, IoprioClassBe),
"io_priority_class_idle" => tests::test_io_priority_class(&spec, IoprioClassIdle),
"devices" => tests::validate_devices(&spec),
_ => eprintln!("error due to unexpected execute test name: {execute_test}"),
}
}
116 changes: 116 additions & 0 deletions tests/contest/runtimetest/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ use oci_spec::runtime::{
IOPriorityClass::{self, IoprioClassBe, IoprioClassIdle, IoprioClassRt},
LinuxSchedulerPolicy, Spec,
};
use oci_spec::runtime::{LinuxDevice, LinuxDeviceType};
use std::fs::{self, read_dir};
use std::mem;
use std::os::linux::fs::MetadataExt;
use std::os::unix::fs::{FileTypeExt, PermissionsExt};
use std::path::Path;

////////// ANCHOR: example_hello_world
Expand Down Expand Up @@ -381,6 +384,119 @@ pub fn validate_scheduler_policy(spec: &Spec) {
}
}

pub fn validate_devices(spec: &Spec) {
let linux = spec.linux().as_ref().unwrap();
if let Some(devices) = linux.devices() {
for (i, device) in devices.iter().enumerate() {
validate_device(
device,
&format!(
"{} (linux.devices[{}])",
device.path().as_path().to_str().unwrap(),
i
),
);
}
}
}

fn validate_device(device: &LinuxDevice, description: &str) {
let file_data = match fs::metadata(device.path()) {
Ok(data) => data,
Err(e) => {
if e.kind() == std::io::ErrorKind::NotFound {
eprintln!(
"error due to device not being present in path: {:?}",
device.path()
);
} else {
eprintln!(
"error due to fail to get metadata for device path {:?}, error: {}",
device.path(),
e
);
}
return;
}
};

let mut expected_type = device.typ();
if expected_type == LinuxDeviceType::U {
expected_type = LinuxDeviceType::C;
}

let file_type = file_data.file_type();
let actual_type = if file_type.is_char_device() {
LinuxDeviceType::C
} else if file_type.is_block_device() {
LinuxDeviceType::B
} else if file_type.is_fifo() {
LinuxDeviceType::P
} else {
LinuxDeviceType::U
};

if actual_type != expected_type {
eprintln!("error due to device type want {expected_type:?}, got {actual_type:?}");
}

if actual_type != LinuxDeviceType::P {
let dev = file_data.st_rdev();
let major = (dev >> 8) & 0xfff;
let minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
if major != device.major() as u64 {
eprintln!(
"error due to device major want {}, got {}",
device.major(),
major
);
}
if minor != device.minor() as u64 {
eprintln!(
"error due to device minor want {}, got {}",
device.minor(),
minor
);
}
}

let expected_permissions = device.file_mode();
if expected_permissions.is_none() {
return;
}

let actual_permissions = file_data.permissions().mode() & 0o777;
if actual_permissions != expected_permissions.unwrap() {
eprintln!("error due to device file mode want {expected_permissions:?}, got {actual_permissions:?}");
}

if description == "/dev/console (default device)" {
eprintln!("we need the major/minor from the controlling TTY");
}

if let Some(expected_uid) = device.uid() {
if file_data.st_uid() != expected_uid {
eprintln!(
"error due to device uid want {}, got {}",
expected_uid,
file_data.st_uid()
);
}
} else {
return;
}

if let Some(expected_gid) = device.gid() {
if file_data.st_gid() != expected_gid {
eprintln!(
"error due to device gid want {}, got {}",
expected_gid,
file_data.st_gid()
);
}
}
}

pub fn test_io_priority_class(spec: &Spec, io_priority_class: IOPriorityClass) {
let io_priority_spec = spec
.process()
Expand Down

0 comments on commit 6f7eaec

Please sign in to comment.