mirror of
https://github.com/containers/youki
synced 2024-11-22 17:02:00 +01:00
add rrelatime mount test (#1642)
Signed-off-by: lengrongfu <1275177125@qq.com>
This commit is contained in:
parent
ef5daba2b4
commit
29babe7d0e
2
.gitignore
vendored
2
.gitignore
vendored
@ -19,4 +19,4 @@ tags.temp
|
||||
*~
|
||||
|
||||
/bundle.tar.gz
|
||||
/test.log
|
||||
/test.log
|
@ -85,7 +85,7 @@ fn get_test(test_name: &'static str) -> Test {
|
||||
delete_hook_output_file();
|
||||
if log != "pre-start1 called\npre-start2 called\npost-start1 called\npost-start2 called\npost-stop1 called\npost-stop2 called\n" {
|
||||
return TestResult::Failed(anyhow!(
|
||||
"error : hooks must be called in the listed order"
|
||||
"error : hooks must be called in the listed order, {log:?}"
|
||||
));
|
||||
}
|
||||
TestResult::Passed
|
||||
|
@ -397,6 +397,106 @@ fn check_recursive_readwrite() -> TestResult {
|
||||
result
|
||||
}
|
||||
|
||||
fn check_recursive_rrelatime() -> TestResult {
|
||||
let rrelatime_base_dir = PathBuf::from_str("/tmp").unwrap();
|
||||
let rrelatime_dir_path = rrelatime_base_dir.join("rrelatime_dir");
|
||||
let rrelatime_suddir_path = rrelatime_dir_path.join("rrelatime_subdir");
|
||||
let mount_dest_path = PathBuf::from_str("/rrelatime").unwrap();
|
||||
fs::create_dir_all(rrelatime_suddir_path).unwrap();
|
||||
|
||||
let mount_options = vec!["rbind".to_string(), "rrelatime".to_string()];
|
||||
let mut mount_spec = Mount::default();
|
||||
mount_spec
|
||||
.set_destination(mount_dest_path)
|
||||
.set_typ(None)
|
||||
.set_source(Some(rrelatime_dir_path.clone()))
|
||||
.set_options(Some(mount_options));
|
||||
let spec = get_spec(
|
||||
vec![mount_spec],
|
||||
vec!["runtimetest".to_string(), "mounts_recursive".to_string()],
|
||||
);
|
||||
let result = test_inside_container(spec, &|_| Ok(()));
|
||||
|
||||
fs::remove_dir_all(rrelatime_dir_path).unwrap();
|
||||
result
|
||||
}
|
||||
|
||||
fn check_recursive_rnorelatime() -> TestResult {
|
||||
let rnorelatime_base_dir = PathBuf::from_str("/tmp").unwrap();
|
||||
let rnorelatime_dir_path = rnorelatime_base_dir.join("rnorelatime_dir");
|
||||
let mount_dest_path = PathBuf::from_str("/rnorelatime").unwrap();
|
||||
fs::create_dir(rnorelatime_dir_path.clone()).unwrap();
|
||||
|
||||
let mount_options = vec!["rbind".to_string(), "rnorelatime".to_string()];
|
||||
let mut mount_spec = Mount::default();
|
||||
mount_spec
|
||||
.set_destination(mount_dest_path)
|
||||
.set_typ(None)
|
||||
.set_source(Some(rnorelatime_dir_path.clone()))
|
||||
.set_options(Some(mount_options));
|
||||
let spec = get_spec(
|
||||
vec![mount_spec],
|
||||
vec!["runtimetest".to_string(), "mounts_recursive".to_string()],
|
||||
);
|
||||
|
||||
let result = test_inside_container(spec, &|_| Ok(()));
|
||||
|
||||
fs::remove_dir_all(rnorelatime_dir_path).unwrap();
|
||||
result
|
||||
}
|
||||
|
||||
fn check_recursive_rnoatime() -> TestResult {
|
||||
let rnoatime_base_dir = PathBuf::from_str("/tmp").unwrap();
|
||||
let rnoatime_dir_path = rnoatime_base_dir.join("rnoatime_dir");
|
||||
let mount_dest_path = PathBuf::from_str("/rnoatime").unwrap();
|
||||
fs::create_dir(rnoatime_dir_path.clone()).unwrap();
|
||||
|
||||
let mount_options = vec!["rbind".to_string(), "rnoatime".to_string()];
|
||||
let mut mount_spec = Mount::default();
|
||||
mount_spec
|
||||
.set_destination(mount_dest_path)
|
||||
.set_typ(None)
|
||||
.set_source(Some(rnoatime_dir_path.clone()))
|
||||
.set_options(Some(mount_options));
|
||||
let spec = get_spec(
|
||||
vec![mount_spec],
|
||||
vec!["runtimetest".to_string(), "mounts_recursive".to_string()],
|
||||
);
|
||||
|
||||
let result = test_inside_container(spec, &|_| Ok(()));
|
||||
|
||||
fs::remove_dir_all(rnoatime_dir_path).unwrap();
|
||||
result
|
||||
}
|
||||
|
||||
fn check_recursive_rstrictatime() -> TestResult {
|
||||
let rstrictatime_base_dir = PathBuf::from_str("/tmp").unwrap();
|
||||
let rstrictatime_dir_path = rstrictatime_base_dir.join("rstrictatime_dir");
|
||||
let mount_dest_path = PathBuf::from_str("/rstrictatime").unwrap();
|
||||
fs::create_dir(rstrictatime_dir_path.clone()).unwrap();
|
||||
|
||||
let mount_options = vec!["rbind".to_string(), "rstrictatime".to_string()];
|
||||
let mut mount_spec = Mount::default();
|
||||
mount_spec
|
||||
.set_destination(mount_dest_path)
|
||||
.set_typ(None)
|
||||
.set_source(Some(rstrictatime_dir_path.clone()))
|
||||
.set_options(Some(mount_options));
|
||||
let spec = get_spec(
|
||||
vec![mount_spec],
|
||||
vec!["runtimetest".to_string(), "mounts_recursive".to_string()],
|
||||
);
|
||||
let result = test_inside_container(spec, &|_| Ok(()));
|
||||
|
||||
fs::remove_dir_all(rstrictatime_dir_path).unwrap();
|
||||
result
|
||||
}
|
||||
|
||||
/// this mount test how to work?
|
||||
/// 1. Create mount_options based on the mount properties of the test
|
||||
/// 2. Create OCI.Spec content, container one process is runtimetest,(runtimetest is cargo model, file path `tests/rust-integration-tests/runtimetest/`)
|
||||
/// 3. inside container to check if the actual mount matches the spec, (spec https://man7.org/linux/man-pages/man2/mount_setattr.2.html),
|
||||
/// eg. tests/rust-integration-tests/runtimetest/src/tests.rs
|
||||
pub fn get_mounts_recursive_test() -> TestGroup {
|
||||
let rro_test = Test::new("rro_test", Box::new(check_recursive_readonly));
|
||||
let rnosuid_test = Test::new("rnosuid_test", Box::new(check_recursive_nosuid));
|
||||
@ -407,6 +507,10 @@ pub fn get_mounts_recursive_test() -> TestGroup {
|
||||
let rnodev_test = Test::new("rnodev_test", Box::new(check_recursive_rnodev));
|
||||
let rrw_test = Test::new("rrw_test", Box::new(check_recursive_readwrite));
|
||||
let rexec_test = Test::new("rexec_test", Box::new(check_recursive_rexec));
|
||||
let rrelatime_test = Test::new("rrelatime_test", Box::new(check_recursive_rrelatime));
|
||||
let rnorelatime_test = Test::new("rnorelatime_test", Box::new(check_recursive_rnorelatime));
|
||||
let rnoatime_test = Test::new("rnoatime_test", Box::new(check_recursive_rnoatime));
|
||||
let rstrictatime_test = Test::new("rstrictatime_test", Box::new(check_recursive_rstrictatime));
|
||||
|
||||
let mut tg = TestGroup::new("mounts_recursive");
|
||||
tg.add(vec![
|
||||
@ -419,6 +523,10 @@ pub fn get_mounts_recursive_test() -> TestGroup {
|
||||
Box::new(rnodev_test),
|
||||
Box::new(rrw_test),
|
||||
Box::new(rexec_test),
|
||||
Box::new(rrelatime_test),
|
||||
Box::new(rnorelatime_test),
|
||||
Box::new(rnoatime_test),
|
||||
Box::new(rstrictatime_test),
|
||||
]);
|
||||
|
||||
tg
|
||||
|
@ -199,6 +199,40 @@ pub fn validate_mounts_recursive(spec: &Spec) {
|
||||
eprintln!("error in testing rnodev recursive mounting");
|
||||
}
|
||||
}
|
||||
"rrelatime" => {
|
||||
println!("rrelatime: {mount:?}");
|
||||
if let Err(e) = utils::test_mount_releatime_option(
|
||||
mount.destination().to_str().unwrap(),
|
||||
) {
|
||||
eprintln!("path expected to be rrelatime, found not rrelatime, error: {e}");
|
||||
}
|
||||
}
|
||||
"rnorelatime" => {
|
||||
println!("rnorelatime: {mount:?}");
|
||||
if let Err(e) = utils::test_mount_noreleatime_option(
|
||||
mount.destination().to_str().unwrap(),
|
||||
) {
|
||||
eprintln!("path expected to be rnorelatime, found not rnorelatime, error: {e}");
|
||||
}
|
||||
}
|
||||
"rnoatime" => {
|
||||
println!("rnoatime: {mount:?}");
|
||||
if let Err(e) = utils::test_mount_rnoatime_option(
|
||||
mount.destination().to_str().unwrap(),
|
||||
) {
|
||||
eprintln!(
|
||||
"path expected to be rnoatime, found not rnoatime, error: {e}"
|
||||
);
|
||||
}
|
||||
}
|
||||
"rstrictatime" => {
|
||||
println!("rstrictatime: {mount:?}");
|
||||
if let Err(e) = utils::test_mount_rstrictatime_option(
|
||||
mount.destination().to_str().unwrap(),
|
||||
) {
|
||||
eprintln!("path expected to be rstrictatime, found not rstrictatime, error: {e}");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use nix::sys::stat::stat;
|
||||
use nix::sys::stat::SFlag;
|
||||
use std::fs;
|
||||
use std::os::unix::prelude::MetadataExt;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
@ -154,3 +155,249 @@ pub fn test_device_unaccess(path: &str) -> Result<(), std::io::Error> {
|
||||
.open(PathBuf::from(path).join("null"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://man7.org/linux/man-pages/man2/mount_setattr.2.html
|
||||
// When a file is accessed via this mount, update the
|
||||
// file's last access time (atime) only if the current
|
||||
// value of atime is less than or equal to the file's
|
||||
// last modification time (mtime) or last status
|
||||
// change time (ctime).
|
||||
// case:
|
||||
// 1. create test.txt file, get one atime
|
||||
// 2. cat a.txt, get two atime; check atime wheather update, conditions are met atime less than or equal mtime or ctime
|
||||
// 3. cat a.txt, get three atime, check now two atime wheather equal three atime
|
||||
pub fn test_mount_releatime_option(path: &str) -> Result<(), std::io::Error> {
|
||||
let test_file_path = PathBuf::from(path).join("test.txt");
|
||||
Command::new("touch")
|
||||
.arg(test_file_path.to_str().unwrap())
|
||||
.output()?;
|
||||
let one_metadata = fs::metadata(test_file_path.clone())?;
|
||||
println!(
|
||||
"{:?} file one metadata atime is {:?},mtime is {:?},current time is{:?}",
|
||||
test_file_path,
|
||||
one_metadata.atime(),
|
||||
one_metadata.mtime(),
|
||||
std::time::SystemTime::now()
|
||||
);
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
|
||||
// execute cat command to update access time
|
||||
Command::new("cat")
|
||||
.arg(test_file_path.to_str().unwrap())
|
||||
.output()
|
||||
.expect("execute cat command error");
|
||||
let two_metadata = fs::metadata(test_file_path.clone())?;
|
||||
println!(
|
||||
"{:?} file two metadata atime is {:?},mtime is {:?},current time is{:?}",
|
||||
test_file_path,
|
||||
two_metadata.atime(),
|
||||
two_metadata.mtime(),
|
||||
std::time::SystemTime::now()
|
||||
);
|
||||
|
||||
if one_metadata.atime() == two_metadata.atime() {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!(
|
||||
"not update access time for file {:?}",
|
||||
test_file_path.to_str()
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
// execute cat command to update access time
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
Command::new("cat")
|
||||
.arg(test_file_path.to_str().unwrap())
|
||||
.output()
|
||||
.expect("execute cat command error");
|
||||
let three_metadata = fs::metadata(test_file_path.clone())?;
|
||||
println!(
|
||||
"{:?} file three metadata atime is {:?}",
|
||||
test_file_path,
|
||||
two_metadata.atime()
|
||||
);
|
||||
if two_metadata.atime() != three_metadata.atime() {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("update access time for file {:?}", test_file_path.to_str()),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// case: because filesystem having relatime option
|
||||
// 1. create test.txt file, get one atime
|
||||
// 2. cat a.txt, get two atime; check atime wheather update
|
||||
// 3. cat a.txt, get three atime, check now two atime wheather equal three atime
|
||||
pub fn test_mount_noreleatime_option(path: &str) -> Result<(), std::io::Error> {
|
||||
let test_file_path = PathBuf::from(path).join("noreleatime.txt");
|
||||
Command::new("touch")
|
||||
.arg(test_file_path.to_str().unwrap())
|
||||
.output()?;
|
||||
let one_metadata = fs::metadata(test_file_path.clone())?;
|
||||
println!(
|
||||
"{:?} file one atime is {:?},mtime is {:?}, current time is {:?}",
|
||||
test_file_path,
|
||||
one_metadata.atime(),
|
||||
one_metadata.mtime(),
|
||||
std::time::SystemTime::now()
|
||||
);
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
// execute cat command to update access time
|
||||
Command::new("cat")
|
||||
.arg(test_file_path.to_str().unwrap())
|
||||
.output()
|
||||
.expect("execute cat command error");
|
||||
let two_metadata = fs::metadata(test_file_path.clone())?;
|
||||
println!(
|
||||
"{:?} file two atime is {:?},mtime is {:?},current time is {:?}",
|
||||
test_file_path,
|
||||
two_metadata.atime(),
|
||||
two_metadata.mtime(),
|
||||
std::time::SystemTime::now()
|
||||
);
|
||||
|
||||
if one_metadata.atime() == two_metadata.atime() {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!(
|
||||
"not update access time for file {:?}",
|
||||
test_file_path.to_str()
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
// execute cat command to update access time
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
Command::new("cat")
|
||||
.arg(test_file_path.to_str().unwrap())
|
||||
.output()
|
||||
.expect("execute cat command error");
|
||||
let three_metadata = fs::metadata(test_file_path.clone())?;
|
||||
println!(
|
||||
"{:?} file three atime is {:?},mtime is {:?},current time is {:?}",
|
||||
test_file_path,
|
||||
two_metadata.atime(),
|
||||
two_metadata.mtime(),
|
||||
std::time::SystemTime::now()
|
||||
);
|
||||
|
||||
if two_metadata.atime() != three_metadata.atime() {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("update access time for file {:?}", test_file_path.to_str()),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Do not update access times for (all types of) files on this mount.
|
||||
// case:
|
||||
// 1. touch rnoatime.txt file, get atime
|
||||
// 2. caat rnoatime.txt, check atime wheather update, if update return error, else return Ok
|
||||
pub fn test_mount_rnoatime_option(path: &str) -> Result<(), std::io::Error> {
|
||||
let test_file_path = PathBuf::from(path).join("rnoatime.txt");
|
||||
Command::new("touch")
|
||||
.arg(test_file_path.to_str().unwrap())
|
||||
.output()?;
|
||||
let one_metadata = fs::metadata(test_file_path.clone())?;
|
||||
println!(
|
||||
"{:?} file one atime is {:?},mtime is {:?}, current time is {:?}",
|
||||
test_file_path,
|
||||
one_metadata.atime(),
|
||||
one_metadata.mtime(),
|
||||
std::time::SystemTime::now()
|
||||
);
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
|
||||
// execute cat command to update access time
|
||||
Command::new("cat")
|
||||
.arg(test_file_path.to_str().unwrap())
|
||||
.output()
|
||||
.expect("execute cat command error");
|
||||
let two_metadata = fs::metadata(test_file_path.clone())?;
|
||||
println!(
|
||||
"{:?} file two atime is {:?},mtime is {:?},current time is {:?}",
|
||||
test_file_path,
|
||||
two_metadata.atime(),
|
||||
two_metadata.mtime(),
|
||||
std::time::SystemTime::now()
|
||||
);
|
||||
if one_metadata.atime() != two_metadata.atime() {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!(
|
||||
"update access time for file {:?}, expected not update",
|
||||
test_file_path.to_str()
|
||||
),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Always update the last access time (atime) when files are accessed on this mount.
|
||||
pub fn test_mount_rstrictatime_option(path: &str) -> Result<(), std::io::Error> {
|
||||
let test_file_path = PathBuf::from(path).join("rstrictatime.txt");
|
||||
Command::new("touch")
|
||||
.arg(test_file_path.to_str().unwrap())
|
||||
.output()?;
|
||||
let one_metadata = fs::metadata(test_file_path.clone())?;
|
||||
println!(
|
||||
"{:?} file one atime is {:?},mtime is {:?}, current time is {:?}",
|
||||
test_file_path,
|
||||
one_metadata.atime(),
|
||||
one_metadata.mtime(),
|
||||
std::time::SystemTime::now()
|
||||
);
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
// execute cat command to update access time
|
||||
Command::new("cat")
|
||||
.arg(test_file_path.to_str().unwrap())
|
||||
.output()
|
||||
.expect("execute cat command error");
|
||||
let two_metadata = fs::metadata(test_file_path.clone())?;
|
||||
println!(
|
||||
"{:?} file two atime is {:?},mtime is {:?},current time is {:?}",
|
||||
test_file_path,
|
||||
two_metadata.atime(),
|
||||
two_metadata.mtime(),
|
||||
std::time::SystemTime::now()
|
||||
);
|
||||
|
||||
if one_metadata.atime() == two_metadata.atime() {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!(
|
||||
"not update access time for file {:?}",
|
||||
test_file_path.to_str()
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
// execute cat command to update access time
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
Command::new("cat")
|
||||
.arg(test_file_path.to_str().unwrap())
|
||||
.output()
|
||||
.expect("execute cat command error");
|
||||
let three_metadata = fs::metadata(test_file_path.clone())?;
|
||||
println!(
|
||||
"{:?} file three atime is {:?},mtime is {:?},current time is {:?}",
|
||||
test_file_path,
|
||||
two_metadata.atime(),
|
||||
two_metadata.mtime(),
|
||||
std::time::SystemTime::now()
|
||||
);
|
||||
|
||||
if two_metadata.atime() == three_metadata.atime() {
|
||||
return Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("update access time for file {:?}", test_file_path.to_str()),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user