276 lines
11 KiB
Diff
276 lines
11 KiB
Diff
|
|
From ac6f7187a7e696e1a90210cbcfb6c649385616ac Mon Sep 17 00:00:00 2001
|
||
|
|
From: chenjiayi <chenjiayi22@huawei.com>
|
||
|
|
Date: Thu, 23 Nov 2023 20:17:49 +0800
|
||
|
|
Subject: [PATCH 084/103] test(devmaster): add UT for execute unit
|
||
|
|
|
||
|
|
---
|
||
|
|
exts/devmaster/src/lib/rules/exec_unit.rs | 255 ++++++++++++++++++++++
|
||
|
|
1 file changed, 255 insertions(+)
|
||
|
|
|
||
|
|
diff --git a/exts/devmaster/src/lib/rules/exec_unit.rs b/exts/devmaster/src/lib/rules/exec_unit.rs
|
||
|
|
index 828fe1af..93684659 100644
|
||
|
|
--- a/exts/devmaster/src/lib/rules/exec_unit.rs
|
||
|
|
+++ b/exts/devmaster/src/lib/rules/exec_unit.rs
|
||
|
|
@@ -987,3 +987,258 @@ fn get_subst_type(
|
||
|
|
*idx = idx_b;
|
||
|
|
Ok(Some((subst, attr)))
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+#[cfg(test)]
|
||
|
|
+mod test {
|
||
|
|
+ use super::*;
|
||
|
|
+ use crate::rules::rules_load::tests::create_tmp_file;
|
||
|
|
+ use device::utils::*;
|
||
|
|
+ use nix::sys::stat::{major, minor};
|
||
|
|
+ use std::cell::RefCell;
|
||
|
|
+ use std::fs::remove_dir_all;
|
||
|
|
+ use std::path::Path;
|
||
|
|
+ use std::rc::Rc;
|
||
|
|
+
|
||
|
|
+ #[test]
|
||
|
|
+ fn test_update_devnode() {
|
||
|
|
+ if let Err(e) = LoopDev::inner_process(
|
||
|
|
+ "/tmp/test_update_devnode_tmpfile",
|
||
|
|
+ 1024 * 1024 * 10,
|
||
|
|
+ |dev| {
|
||
|
|
+ let dev = Rc::new(RefCell::new(dev.shallow_clone().unwrap()));
|
||
|
|
+ let id = dev.borrow().get_device_id().unwrap();
|
||
|
|
+ let devnum = dev.borrow().get_devnum().unwrap();
|
||
|
|
+ let major_minor = format!("{}:{}", major(devnum), minor(devnum));
|
||
|
|
+
|
||
|
|
+ create_tmp_file("/tmp/test_update_devnode/data", &id, "", true);
|
||
|
|
+
|
||
|
|
+ dev.borrow().sealed.replace(true);
|
||
|
|
+ dev.borrow().set_base_path("/tmp/test_update_devnode");
|
||
|
|
+ dev.borrow().set_devgid("1").unwrap();
|
||
|
|
+ dev.borrow().set_devuid("1").unwrap();
|
||
|
|
+ dev.borrow().set_devmode("666").unwrap();
|
||
|
|
+ dev.borrow().add_devlink("test_update_devnode/bbb").unwrap();
|
||
|
|
+
|
||
|
|
+ let mut unit = ExecuteUnitData::new(dev.clone());
|
||
|
|
+ unit.clone_device_db().unwrap();
|
||
|
|
+
|
||
|
|
+ unit.update_devnode(&HashMap::new()).unwrap();
|
||
|
|
+ /* Record the devlink in db */
|
||
|
|
+ dev.borrow().update_db().unwrap();
|
||
|
|
+
|
||
|
|
+ let p = Path::new("/dev/test_update_devnode/bbb");
|
||
|
|
+ let p_block_s = format!("/dev/block/{}", major_minor);
|
||
|
|
+ let prior_p_s = format!("/run/devmaster/links/test_update_devnode\\x2fbbb/{}", id);
|
||
|
|
+ let prior_p = Path::new(&prior_p_s);
|
||
|
|
+ assert!(p.exists());
|
||
|
|
+ assert!(Path::new(&p_block_s).exists());
|
||
|
|
+ assert!(p
|
||
|
|
+ .canonicalize()
|
||
|
|
+ .unwrap()
|
||
|
|
+ .ends_with(&dev.borrow().get_sysname().unwrap()));
|
||
|
|
+ let _ = prior_p.symlink_metadata().unwrap(); // Test symlink exists.
|
||
|
|
+
|
||
|
|
+ let new_dev = Rc::new(RefCell::new(Device::from_device_id(&id).unwrap()));
|
||
|
|
+ new_dev.borrow().sealed.replace(true);
|
||
|
|
+ new_dev.borrow().set_base_path("/tmp/test_update_devnode");
|
||
|
|
+ new_dev.borrow().set_devgid("0").unwrap();
|
||
|
|
+ new_dev.borrow().set_devuid("0").unwrap();
|
||
|
|
+ new_dev.borrow().set_devmode("600").unwrap();
|
||
|
|
+
|
||
|
|
+ let mut unit = ExecuteUnitData::new(new_dev);
|
||
|
|
+ /* See the devlink in db, but it is absent in the current device object.
|
||
|
|
+ *
|
||
|
|
+ * Then update_devnode method will remove the devlink.
|
||
|
|
+ */
|
||
|
|
+ unit.clone_device_db().unwrap();
|
||
|
|
+ unit.update_devnode(&HashMap::new()).unwrap();
|
||
|
|
+
|
||
|
|
+ assert!(!Path::new("/dev/test_update_devnode/bbb").exists());
|
||
|
|
+ assert!(Path::new(&p_block_s).exists());
|
||
|
|
+ let _ = prior_p.symlink_metadata().unwrap_err(); // Test symlink does not exists.
|
||
|
|
+
|
||
|
|
+ remove_dir_all("/tmp/test_update_devnode").unwrap();
|
||
|
|
+
|
||
|
|
+ /* Non-block devices do not have device nodes, thus update_devnode method will do nothing. */
|
||
|
|
+ let lo = Rc::new(RefCell::new(
|
||
|
|
+ Device::from_subsystem_sysname("net", "lo").unwrap(),
|
||
|
|
+ ));
|
||
|
|
+
|
||
|
|
+ let mut unit = ExecuteUnitData::new(lo);
|
||
|
|
+ unit.update_devnode(&HashMap::new()).unwrap();
|
||
|
|
+
|
||
|
|
+ /* Cover error paths when uid, gid or mode is not set. */
|
||
|
|
+ let dev = Rc::new(RefCell::new(Device::from_device_id(&id).unwrap()));
|
||
|
|
+ dev.borrow().sealed.replace(true);
|
||
|
|
+ dev.borrow().add_devlink("test_update_devnode/xxx").unwrap();
|
||
|
|
+
|
||
|
|
+ let mut unit = ExecuteUnitData::new(dev.clone());
|
||
|
|
+ unit.clone_device_db().unwrap();
|
||
|
|
+ unit.update_devnode(&HashMap::new()).unwrap();
|
||
|
|
+
|
||
|
|
+ let p = Path::new("/dev/test_update_devnode/xxx");
|
||
|
|
+ let prior_p_s = format!("/run/devmaster/links/test_update_devnode\\x2fxxx/{}", id);
|
||
|
|
+ assert!(p.exists());
|
||
|
|
+ assert!(Path::new(&p_block_s).exists());
|
||
|
|
+ assert!(p
|
||
|
|
+ .canonicalize()
|
||
|
|
+ .unwrap()
|
||
|
|
+ .ends_with(&dev.borrow().get_sysname().unwrap()));
|
||
|
|
+ let _ = Path::new(&prior_p_s).symlink_metadata().unwrap(); // Test symlink exists.
|
||
|
|
+
|
||
|
|
+ cleanup_node(dev).unwrap();
|
||
|
|
+
|
||
|
|
+ assert!(!p.exists());
|
||
|
|
+ assert!(!Path::new(&p_block_s).exists());
|
||
|
|
+ let _ = Path::new(&prior_p_s).symlink_metadata().unwrap_err(); // Test symlink exists.
|
||
|
|
+
|
||
|
|
+ Ok(())
|
||
|
|
+ },
|
||
|
|
+ ) {
|
||
|
|
+ assert!(e.is_errno(nix::Error::EACCES) || e.is_errno(nix::Error::EBUSY));
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ #[test]
|
||
|
|
+ fn test_subst_format() {
|
||
|
|
+ if let Err(e) =
|
||
|
|
+ LoopDev::inner_process("/tmp/test_subst_format_tmpfile", 1024 * 1024 * 10, |dev| {
|
||
|
|
+ let dev = Rc::new(RefCell::new(dev.shallow_clone().unwrap()));
|
||
|
|
+ let mut unit = ExecuteUnitData::new(dev.clone());
|
||
|
|
+ let devnum = dev.borrow().get_devnum().unwrap();
|
||
|
|
+ let major_minor = format!("{}:{}", major(devnum), minor(devnum));
|
||
|
|
+ let sysname = dev.borrow().get_sysname().unwrap();
|
||
|
|
+
|
||
|
|
+ assert_eq!(
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Attr, Some("dev".to_string()))
|
||
|
|
+ .unwrap(),
|
||
|
|
+ major_minor
|
||
|
|
+ );
|
||
|
|
+
|
||
|
|
+ assert_eq!(
|
||
|
|
+ unit.subst_format(
|
||
|
|
+ FormatSubstitutionType::Attr,
|
||
|
|
+ Some(format!("[block/{}]dev", sysname))
|
||
|
|
+ )
|
||
|
|
+ .unwrap(),
|
||
|
|
+ major_minor
|
||
|
|
+ );
|
||
|
|
+
|
||
|
|
+ unit.set_parent(Some(Rc::new(RefCell::new(
|
||
|
|
+ Device::from_subsystem_sysname("net", "lo").unwrap(),
|
||
|
|
+ ))));
|
||
|
|
+
|
||
|
|
+ /* Get the sysattr of parent device set in unit. */
|
||
|
|
+ assert_eq!(
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Attr, Some("ifindex".to_string()))
|
||
|
|
+ .unwrap(),
|
||
|
|
+ "1".to_string()
|
||
|
|
+ );
|
||
|
|
+
|
||
|
|
+ /* Invalid sysattr will be replaced with empty string. */
|
||
|
|
+ assert!(unit
|
||
|
|
+ .subst_format(
|
||
|
|
+ FormatSubstitutionType::Attr,
|
||
|
|
+ Some("asdfasdfads".to_string())
|
||
|
|
+ )
|
||
|
|
+ .unwrap()
|
||
|
|
+ .is_empty());
|
||
|
|
+
|
||
|
|
+ dev.borrow().add_property("hello", "world").unwrap();
|
||
|
|
+
|
||
|
|
+ assert_eq!(
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Env, Some("hello".to_string()))
|
||
|
|
+ .unwrap(),
|
||
|
|
+ "world".to_string()
|
||
|
|
+ );
|
||
|
|
+
|
||
|
|
+ assert!(unit
|
||
|
|
+ .subst_format(FormatSubstitutionType::Env, Some("asdfgasd".to_string()))
|
||
|
|
+ .unwrap()
|
||
|
|
+ .is_empty());
|
||
|
|
+
|
||
|
|
+ assert!(unit
|
||
|
|
+ .subst_format(FormatSubstitutionType::Driver, None)
|
||
|
|
+ .unwrap()
|
||
|
|
+ .is_empty());
|
||
|
|
+
|
||
|
|
+ assert_eq!(
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Id, None).unwrap(),
|
||
|
|
+ "lo".to_string()
|
||
|
|
+ );
|
||
|
|
+
|
||
|
|
+ let major = unit
|
||
|
|
+ .subst_format(FormatSubstitutionType::Major, None)
|
||
|
|
+ .unwrap();
|
||
|
|
+ let minor = unit
|
||
|
|
+ .subst_format(FormatSubstitutionType::Minor, None)
|
||
|
|
+ .unwrap();
|
||
|
|
+ assert_eq!(format!("{}:{}", major, minor), major_minor);
|
||
|
|
+
|
||
|
|
+ unit.program_result = "hello world test".to_string();
|
||
|
|
+ assert_eq!(
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Result, None)
|
||
|
|
+ .unwrap(),
|
||
|
|
+ "hello world test".to_string()
|
||
|
|
+ );
|
||
|
|
+ assert_eq!(
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Result, Some("0".to_string()))
|
||
|
|
+ .unwrap(),
|
||
|
|
+ "hello".to_string()
|
||
|
|
+ );
|
||
|
|
+ assert_eq!(
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Result, Some("1+".to_string()))
|
||
|
|
+ .unwrap(),
|
||
|
|
+ "world test".to_string()
|
||
|
|
+ );
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Result, Some("x".to_string()))
|
||
|
|
+ .unwrap_err();
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Result, Some("x+".to_string()))
|
||
|
|
+ .unwrap_err();
|
||
|
|
+
|
||
|
|
+ assert!(unit
|
||
|
|
+ .subst_format(FormatSubstitutionType::Result, Some("3+".to_string()))
|
||
|
|
+ .unwrap()
|
||
|
|
+ .is_empty());
|
||
|
|
+
|
||
|
|
+ assert_eq!(
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Name, None)
|
||
|
|
+ .unwrap(),
|
||
|
|
+ sysname
|
||
|
|
+ );
|
||
|
|
+
|
||
|
|
+ unit.name = "test".to_string();
|
||
|
|
+ assert_eq!(
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Name, None)
|
||
|
|
+ .unwrap(),
|
||
|
|
+ "test".to_string(),
|
||
|
|
+ );
|
||
|
|
+
|
||
|
|
+ dev.borrow().add_devlink("test").unwrap();
|
||
|
|
+ dev.borrow().sealed.replace(true);
|
||
|
|
+ assert_eq!(
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Links, None)
|
||
|
|
+ .unwrap(),
|
||
|
|
+ "test".to_string(),
|
||
|
|
+ );
|
||
|
|
+
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Invalid, None)
|
||
|
|
+ .unwrap_err();
|
||
|
|
+
|
||
|
|
+ Ok(())
|
||
|
|
+ })
|
||
|
|
+ {
|
||
|
|
+ assert!(e.is_errno(nix::Error::EACCES) || e.is_errno(nix::Error::EBUSY));
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ let dev = Rc::new(RefCell::new(
|
||
|
|
+ Device::from_subsystem_sysname("net", "lo").unwrap(),
|
||
|
|
+ ));
|
||
|
|
+ let unit = ExecuteUnitData::new(dev);
|
||
|
|
+ assert_eq!(
|
||
|
|
+ unit.subst_format(FormatSubstitutionType::Name, None)
|
||
|
|
+ .unwrap(),
|
||
|
|
+ "lo".to_string()
|
||
|
|
+ );
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
--
|
||
|
|
2.33.0
|
||
|
|
|