sync patches from upstream

This commit is contained in:
chenjiayi 2023-12-07 00:19:38 +08:00
parent b7cf752d42
commit 7234106002
44 changed files with 12759 additions and 2 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,199 @@
From 714eeceecbe09fd8855cd84279dc13e45a093fb2 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Thu, 16 Nov 2023 08:07:07 +0800
Subject: [PATCH 064/103] feature(devmaster): add devctl control subcommand to
let devmaster exit
Also decouple the configuration path into the parameter of run_daemon
function for unit test.
---
exts/devmaster/src/bin/devctl/daemon/mod.rs | 37 ++++++++++++++++++-
exts/devmaster/src/bin/devctl/main.rs | 19 +++++++++-
.../src/lib/framework/control_manager.rs | 9 ++++-
exts/devmaster/src/lib/framework/devmaster.rs | 5 ++-
4 files changed, 63 insertions(+), 7 deletions(-)
diff --git a/exts/devmaster/src/bin/devctl/daemon/mod.rs b/exts/devmaster/src/bin/devctl/daemon/mod.rs
index 6dfe9718..3e4bd96d 100644
--- a/exts/devmaster/src/bin/devctl/daemon/mod.rs
+++ b/exts/devmaster/src/bin/devctl/daemon/mod.rs
@@ -38,10 +38,10 @@ fn notify(unset_env: bool, msg: String) -> std::io::Result<()> {
}
}
-pub fn run_daemon() {
+pub fn run_daemon(config_path: &str) {
let events = Rc::new(Events::new().unwrap());
- let devmaster = Devmaster::new(events);
+ let devmaster = Devmaster::new(config_path, events);
if let Err(e) = notify(false, "READY=1\n".to_string()) {
log::warn!("Failed to notify pid 1: {}", e);
@@ -51,3 +51,36 @@ pub fn run_daemon() {
devmaster.as_ref().borrow().exit();
}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use device::{Device, DeviceAction};
+ use libdevmaster::framework::control_manager::CONTROL_MANAGER_LISTEN_ADDR;
+ use std::io::Write;
+
+ #[test]
+ fn test_run_daemon() {
+ /* Require root privilege, skip in ci environment. */
+ let dev = Device::from_subsystem_sysname("net", "lo").unwrap();
+ if dev.trigger(DeviceAction::Change).is_err() {
+ return;
+ }
+
+ std::thread::spawn(|| {
+ std::thread::sleep(std::time::Duration::from_secs(1));
+
+ let dev = Device::from_subsystem_sysname("net", "lo").unwrap();
+ dev.trigger(DeviceAction::Change).unwrap();
+
+ /* Sleep more than 3 seconds to wait for the workers being recycled. */
+ std::thread::sleep(std::time::Duration::from_secs(4));
+
+ let mut stream =
+ std::os::unix::net::UnixStream::connect(CONTROL_MANAGER_LISTEN_ADDR).unwrap();
+ stream.write_all(b"exit ").unwrap();
+ });
+
+ run_daemon("none");
+ }
+}
diff --git a/exts/devmaster/src/bin/devctl/main.rs b/exts/devmaster/src/bin/devctl/main.rs
index 17645ee6..8f72285e 100644
--- a/exts/devmaster/src/bin/devctl/main.rs
+++ b/exts/devmaster/src/bin/devctl/main.rs
@@ -18,6 +18,7 @@ mod subcmds;
use basic::argv_util::invoked_as;
use clap::Parser;
use daemon::run_daemon;
+use libdevmaster::config::devmaster_conf::DEFAULT_CONFIG;
use libdevmaster::framework::control_manager::CONTROL_MANAGER_LISTEN_ADDR;
use log::init_log_to_console_syslog;
use log::Level;
@@ -204,6 +205,12 @@ enum SubCmd {
#[clap(short, long)]
root: Option<String>,
},
+ ///
+ #[clap(display_order = 7)]
+ Control {
+ #[clap(short, long)]
+ exit: bool,
+ },
}
/// subcommand for killing workers
@@ -212,10 +219,19 @@ fn subcommand_kill() {
stream.write_all(b"kill ").unwrap();
}
+/// subcommand for controlling devmaster
+fn subcommand_control(exit: bool) {
+ let mut stream = UnixStream::connect(CONTROL_MANAGER_LISTEN_ADDR).unwrap();
+
+ if exit {
+ stream.write_all(b"exit ").unwrap();
+ }
+}
+
fn main() -> Result<()> {
let argv: Vec<String> = std::env::args().collect();
if invoked_as(argv, "devmaster") {
- run_daemon();
+ run_daemon(DEFAULT_CONFIG);
return Ok(());
}
@@ -300,6 +316,7 @@ fn main() -> Result<()> {
strict,
root,
} => subcommand_hwdb(update, test, path, usr, strict, root),
+ SubCmd::Control { exit } => subcommand_control(exit),
}
Ok(())
diff --git a/exts/devmaster/src/lib/framework/control_manager.rs b/exts/devmaster/src/lib/framework/control_manager.rs
index 342c6a0c..d5a5f440 100644
--- a/exts/devmaster/src/lib/framework/control_manager.rs
+++ b/exts/devmaster/src/lib/framework/control_manager.rs
@@ -14,7 +14,7 @@
//!
use crate::framework::job_queue::JobQueue;
use crate::framework::worker_manager::WorkerManager;
-use event::Source;
+use event::{Events, Source};
use nix::unistd::unlink;
use std::os::unix::net::UnixListener;
use std::path::Path;
@@ -38,7 +38,7 @@ pub struct ControlManager {
worker_manager: Weak<WorkerManager>,
/// reference to job queue
_job_queue: Weak<JobQueue>,
- // events: Rc<Events>,
+ events: Rc<Events>,
}
/// public methods
@@ -48,6 +48,7 @@ impl ControlManager {
listen_addr: String,
worker_manager: Rc<WorkerManager>,
job_queue: Rc<JobQueue>,
+ events: Rc<Events>,
) -> ControlManager {
/*
* Cleanup remaining socket if it exists.
@@ -67,6 +68,7 @@ impl ControlManager {
listener,
worker_manager: Rc::downgrade(&worker_manager),
_job_queue: Rc::downgrade(&job_queue),
+ events,
}
}
}
@@ -83,6 +85,9 @@ impl ControlManager {
"kill" => {
self.worker_manager.upgrade().unwrap().kill_workers();
}
+ "exit" => {
+ self.events.set_exit();
+ }
_ => {
todo!();
}
diff --git a/exts/devmaster/src/lib/framework/devmaster.rs b/exts/devmaster/src/lib/framework/devmaster.rs
index 94b93ca0..20735614 100644
--- a/exts/devmaster/src/lib/framework/devmaster.rs
+++ b/exts/devmaster/src/lib/framework/devmaster.rs
@@ -71,10 +71,10 @@ impl Cache {
impl Devmaster {
/// generate a devmaster object
- pub fn new(events: Rc<Events>) -> Rc<RefCell<Devmaster>> {
+ pub fn new(config_path: &str, events: Rc<Events>) -> Rc<RefCell<Devmaster>> {
let config = DevmasterConfig::new();
- config.load(DEFAULT_CONFIG);
+ config.load(config_path);
init_log(
"devmaster",
@@ -127,6 +127,7 @@ impl Devmaster {
String::from(CONTROL_MANAGER_LISTEN_ADDR),
worker_manager.clone(),
job_queue.clone(),
+ events.clone(),
));
let monitor = Rc::new(UeventMonitor::new(job_queue.clone()));
let post = Rc::new(GarbageCollect::new(&devmaster));
--
2.33.0

View File

@ -0,0 +1,157 @@
From b5b35912af30bd37d38496af6a28aec5cd27159e Mon Sep 17 00:00:00 2001
From: huyubiao <huyubiao@huawei.com>
Date: Wed, 8 Nov 2023 06:53:14 +0800
Subject: [PATCH 038/103] fix: Failed to devctl info /dev or /sys
---
.../src/bin/devctl/subcmds/devctl_info.rs | 67 ++++++-------------
1 file changed, 21 insertions(+), 46 deletions(-)
diff --git a/exts/devmaster/src/bin/devctl/subcmds/devctl_info.rs b/exts/devmaster/src/bin/devctl/subcmds/devctl_info.rs
index e18c3898..71c9254d 100644
--- a/exts/devmaster/src/bin/devctl/subcmds/devctl_info.rs
+++ b/exts/devmaster/src/bin/devctl/subcmds/devctl_info.rs
@@ -35,20 +35,6 @@ enum QueryType {
All,
}
-struct QueryProperty {
- export: bool,
- export_prefix: Option<String>,
-}
-
-impl QueryProperty {
- fn new(export: bool, export_prefix: Option<String>) -> Self {
- QueryProperty {
- export,
- export_prefix,
- }
- }
-}
-
struct SysAttr {
name: String,
value: String,
@@ -96,11 +82,6 @@ impl InfoArgs {
pub fn subcommand(&self) -> Result<()> {
let mut devs = Vec::new();
- let mut arg_export = false;
- if self.export || self.export_prefix.is_some() {
- arg_export = true;
- }
-
if self.export_db {
return export_devices();
}
@@ -113,12 +94,9 @@ impl InfoArgs {
log::error!("Positional arguments are not allowed with -d/--device-id-of-file.");
return Err(nix::Error::EINVAL);
}
- return self.stat_device(name, arg_export);
+ return self.stat_device(name);
}
- let mut query_type = QueryType::All;
- self.parse_query_type(&mut query_type)?;
-
devs.extend(&self.devices);
if devs.is_empty() {
log::error!("A device name or path is required");
@@ -145,43 +123,44 @@ impl InfoArgs {
};
if self.query.is_some() {
- let query_property = QueryProperty::new(arg_export, self.export_prefix.clone());
- r = self.query_device(&query_type, device, query_property);
+ r = self.query_device(device);
} else if self.attribute_walk {
r = print_device_chain(device);
} else {
- log::error!("unknown action");
- return Err(nix::Error::EINVAL);
+ r = self.query_device(device);
}
}
r
}
- fn parse_query_type(&self, query_type: &mut QueryType) -> Result<()> {
+ fn is_export(&self) -> bool {
+ self.export || self.export_prefix.is_some()
+ }
+
+ fn parse_query_type(&self) -> Result<QueryType> {
match &self.query {
Some(q) => {
if q == "property" || q == "env" {
- *query_type = QueryType::Property;
+ Ok(QueryType::Property)
} else if q == "name" {
- *query_type = QueryType::Name;
+ Ok(QueryType::Name)
} else if q == "symlink" {
- *query_type = QueryType::Symlink;
+ Ok(QueryType::Symlink)
} else if q == "path" {
- *query_type = QueryType::Path;
+ Ok(QueryType::Path)
} else if q == "all" {
- *query_type = QueryType::All;
+ Ok(QueryType::All)
} else {
log::error!("unknown query type");
- return Err(nix::Error::EINVAL);
+ Err(nix::Error::EINVAL)
}
}
- None => *query_type = QueryType::All,
+ None => Ok(QueryType::All),
}
- Ok(())
}
- fn stat_device(&self, name: &str, export: bool) -> Result<()> {
+ fn stat_device(&self, name: &str) -> Result<()> {
let metadata = match fs::metadata(name) {
Ok(metadata) => metadata,
Err(err) => {
@@ -190,7 +169,7 @@ impl InfoArgs {
}
};
- if export {
+ if self.is_export() {
match &self.export_prefix {
Some(p) => {
println!("{}MAJOR={}", p, nix::sys::stat::major(metadata.dev()));
@@ -212,12 +191,8 @@ impl InfoArgs {
Ok(())
}
- fn query_device(
- &self,
- query: &QueryType,
- device: Device,
- property: QueryProperty,
- ) -> Result<()> {
+ fn query_device(&self, device: Device) -> Result<()> {
+ let query = self.parse_query_type()?;
match query {
QueryType::Name => {
let node = match device.get_devname() {
@@ -275,8 +250,8 @@ impl InfoArgs {
}
QueryType::Property => {
for (key, value) in &device.property_iter() {
- if property.export {
- match &property.export_prefix {
+ if self.is_export() {
+ match &self.export_prefix {
Some(export_prefix) => println!("{}{}='{}'", export_prefix, key, value),
None => println!("{}='{}'", key, value),
}
--
2.33.0

View File

@ -0,0 +1,81 @@
From 241471ed8d54b769831fc383075233df967a897a Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Wed, 8 Nov 2023 02:09:09 +0800
Subject: [PATCH 045/103] fix(basic): complete feature dependencies
uuid depends on random.
random depends on io.
Also add get_errno method for basic Error.
---
libs/basic/Cargo.toml | 4 ++--
libs/basic/src/error.rs | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/libs/basic/Cargo.toml b/libs/basic/Cargo.toml
index f7c84157..654c1a3b 100644
--- a/libs/basic/Cargo.toml
+++ b/libs/basic/Cargo.toml
@@ -111,9 +111,9 @@ string = []
sysfs = ["nix/dir"]
unistd = ["nix/user"]
unit_name = []
-uuid = ["bitflags"]
+uuid = ["bitflags", "random"]
murmurhash2 = []
strbuf = []
argv = []
exec_util = []
-random = []
+random = ["io"]
diff --git a/libs/basic/src/error.rs b/libs/basic/src/error.rs
index aead8ce7..d138f477 100644
--- a/libs/basic/src/error.rs
+++ b/libs/basic/src/error.rs
@@ -70,6 +70,42 @@ pub enum Error {
Other { msg: String },
}
+impl Error {
+ /// Translate the basic error to error number.
+ pub fn get_errno(&self) -> i32 {
+ match self {
+ Self::Syscall {
+ syscall: _,
+ ret: _,
+ errno,
+ } => *errno,
+ Error::Io { source } => source.raw_os_error().unwrap_or_default(),
+ Error::Caps { what: _ } => nix::errno::Errno::EINVAL as i32,
+ Error::Nix { source } => *source as i32,
+ Error::Var { source } => {
+ (match source {
+ std::env::VarError::NotPresent => nix::errno::Errno::ENOENT,
+ std::env::VarError::NotUnicode(_) => nix::errno::Errno::EINVAL,
+ }) as i32
+ }
+ Error::Proc { source } => match source {
+ procfs::ProcError::Incomplete(_) => nix::errno::Errno::EINVAL as i32,
+ procfs::ProcError::PermissionDenied(_) => nix::errno::Errno::EPERM as i32,
+ procfs::ProcError::NotFound(_) => nix::errno::Errno::ENOENT as i32,
+ procfs::ProcError::Io(_, _) => nix::errno::Errno::EIO as i32,
+ procfs::ProcError::Other(_) => nix::errno::Errno::EINVAL as i32,
+ procfs::ProcError::InternalError(_) => nix::errno::Errno::EINVAL as i32,
+ },
+ Error::NulError { source: _ } => nix::errno::Errno::EINVAL as i32,
+ Error::Parse { source: _ } => nix::errno::Errno::EINVAL as i32,
+ Error::ParseNamingScheme { what: _ } => nix::errno::Errno::EINVAL as i32,
+ Error::NotExisted { what: _ } => nix::errno::Errno::ENOENT as i32,
+ Error::Invalid { what: _ } => nix::errno::Errno::EINVAL as i32,
+ Error::Other { msg: _ } => nix::errno::Errno::EINVAL as i32,
+ }
+ }
+}
+
#[allow(unused_macros)]
macro_rules! errfrom {
($($st:ty),* => $variant:ident) => (
--
2.33.0

View File

@ -0,0 +1,25 @@
From 9af6528c348feab7c463a0710f6dacc8ac57db95 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Wed, 8 Nov 2023 05:17:04 +0800
Subject: [PATCH 048/103] fix(basic): use feature to control procfs compilation
in get_errno
---
libs/basic/src/error.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/libs/basic/src/error.rs b/libs/basic/src/error.rs
index d138f477..89ac5a3e 100644
--- a/libs/basic/src/error.rs
+++ b/libs/basic/src/error.rs
@@ -88,6 +88,7 @@ impl Error {
std::env::VarError::NotUnicode(_) => nix::errno::Errno::EINVAL,
}) as i32
}
+ #[cfg(feature = "process")]
Error::Proc { source } => match source {
procfs::ProcError::Incomplete(_) => nix::errno::Errno::EINVAL as i32,
procfs::ProcError::PermissionDenied(_) => nix::errno::Errno::EPERM as i32,
--
2.33.0

View File

@ -0,0 +1,86 @@
From a71d702d98d090eb0bc68fa7950a590967de8716 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Thu, 23 Nov 2023 14:23:46 +0800
Subject: [PATCH 082/103] fix(device): avoid panic on shallow clone when
subsystem is not available
Some special sysfs device, such as /sys/devices/platform, may not contain
available subsystem. This leads to panic in shallow cloning such device
object when getting its subsystem.
---
libs/device/src/device.rs | 51 ++++++++++++++++++++++++---------------
1 files changed, 32 insertions(+), 19 deletions(-)
diff --git a/libs/device/src/device.rs b/libs/device/src/device.rs
index e8e2dcc5..a9cb196c 100644
--- a/libs/device/src/device.rs
+++ b/libs/device/src/device.rs
@@ -2396,14 +2396,15 @@ impl Device {
device.set_syspath(&syspath, false)?;
- let subsystem = self.get_subsystem()?;
+ /* Some devices, such as /sys/devices/platform, do not have subsystem. */
+ if let Ok(subsystem) = self.get_subsystem() {
+ device.set_subsystem(&subsystem);
- device.set_subsystem(&subsystem);
-
- if subsystem == "drivers" {
- device
- .driver_subsystem
- .replace(self.driver_subsystem.borrow().clone());
+ if subsystem == "drivers" {
+ device
+ .driver_subsystem
+ .replace(self.driver_subsystem.borrow().clone());
+ }
}
if let Ok(ifindex) = self.get_property_value("IFINDEX") {
@@ -3506,19 +3507,31 @@ mod tests {
#[test]
fn test_shallow_clone() {
- #[inline]
- fn inner_test(dev: &mut Device) -> Result<(), Error> {
- let s1 = dev.get_syspath().unwrap();
-
- let dev_clone = dev.shallow_clone().unwrap();
-
- assert_eq!(s1, dev_clone.get_syspath().unwrap());
-
- Ok(())
- }
+ /* Enumerator merely collect devices with valid subsystems,
+ * while get_parent method may not, e.g., /sys/devices/platform.
+ */
+ let mut e = DeviceEnumerator::new();
+ e.set_enumerator_type(DeviceEnumerationType::All);
+
+ for mut dev in e.iter() {
+ let dev_clone = dev.borrow().shallow_clone().unwrap();
+ dev_clone.get_syspath().unwrap();
+ dev_clone.get_subsystem().unwrap();
+
+ loop {
+ let ret = dev.borrow().get_parent();
+
+ if let Ok(parent) = ret {
+ parent.borrow().get_syspath().unwrap();
+ if let Err(e) = parent.borrow().get_subsystem() {
+ assert_eq!(e.get_errno(), Errno::ENOENT);
+ }
+ dev = parent;
+ continue;
+ }
- if let Err(e) = LoopDev::inner_process("/tmp/test_shallow_clone", 1024 * 10, inner_test) {
- assert!(e.is_errno(nix::Error::EACCES) || e.is_errno(nix::Error::EBUSY));
+ break;
+ }
}
}
2.33.0

View File

@ -0,0 +1,35 @@
From 23a1923d6ef767e1f49a18129e515a67bf4ff70c Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Tue, 14 Nov 2023 22:35:01 +0800
Subject: [PATCH 060/103] fix(device): cleanup temporary tag files
Also make a tiny change to optimize the doc conmments.
---
libs/device/src/device.rs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/libs/device/src/device.rs b/libs/device/src/device.rs
index 6a43be82..70070c72 100644
--- a/libs/device/src/device.rs
+++ b/libs/device/src/device.rs
@@ -2774,7 +2774,7 @@ impl Device {
}
/// Return the devlink iterator
- ///
+ ///
/// The device object will try to load devlinks from db firstly.
pub fn devlink_iter(&self) -> HashSetRefWrapper<String> {
let _ = self.read_db();
@@ -3452,6 +3452,8 @@ mod tests {
dev.cleanup_tags();
+ fs::remove_dir_all("/tmp/devmaster").unwrap();
+
Ok(())
}
--
2.33.0

View File

@ -0,0 +1,96 @@
From ed46964df74ff592f39295fe20d083b144089310 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Tue, 14 Nov 2023 17:14:36 +0800
Subject: [PATCH 059/103] fix(device): drop unnecessary error throwing out
In some device methods, the device object should prepare inner data by reading
database, but it tolerates failure.
---
libs/device/src/device.rs | 43 +++++++++++++--------------------------
1 file changed, 14 insertions(+), 29 deletions(-)
diff --git a/libs/device/src/device.rs b/libs/device/src/device.rs
index 3845e21c..6a43be82 100644
--- a/libs/device/src/device.rs
+++ b/libs/device/src/device.rs
@@ -955,14 +955,14 @@ impl Device {
/// check whether the device has the tag
pub fn has_tag(&self, tag: &str) -> Result<bool, Error> {
- self.read_db()?;
+ let _ = self.read_db();
Ok(self.all_tags.borrow().contains(tag))
}
/// check whether the device has the current tag
pub fn has_current_tag(&self, tag: &str) -> Result<bool, Error> {
- self.read_db()?;
+ let _ = self.read_db();
Ok(self.current_tags.borrow().contains(tag))
}
@@ -2751,48 +2751,33 @@ impl<'a, 'b: 'a, K: 'a, V: 'a> IntoIterator for &'b HashMapRefWrapper<'a, K, V>
}
impl Device {
- /// return the tag iterator
+ /// Return the tag iterator.
+ ///
+ /// The device object will try to load tags from db firstly.
pub fn tag_iter(&self) -> HashSetRefWrapper<String> {
- if let Err(e) = self.read_db() {
- log::debug!(
- "failed to read db of '{}': {}",
- self.get_device_id()
- .unwrap_or_else(|_| self.devpath.borrow().clone()),
- e
- )
- }
+ let _ = self.read_db();
HashSetRefWrapper {
r: self.all_tags.borrow(),
}
}
- /// return the current tag iterator
+ /// Return the current tag iterator.
+ ///
+ /// The device object will try to load tags from db firstly.
pub fn current_tag_iter(&self) -> HashSetRefWrapper<String> {
- if let Err(e) = self.read_db() {
- log::error!(
- "failed to read db of '{}': {}",
- self.get_device_id()
- .unwrap_or_else(|_| self.devpath.borrow().clone()),
- e
- )
- }
+ let _ = self.read_db();
HashSetRefWrapper {
r: self.current_tags.borrow(),
}
}
- /// return the tag iterator
+ /// Return the devlink iterator
+ ///
+ /// The device object will try to load devlinks from db firstly.
pub fn devlink_iter(&self) -> HashSetRefWrapper<String> {
- if let Err(e) = self.read_db() {
- log::debug!(
- "failed to read db of '{}': {}",
- self.get_device_id()
- .unwrap_or_else(|_| self.devpath.borrow().clone()),
- e
- )
- }
+ let _ = self.read_db();
HashSetRefWrapper {
r: self.devlinks.borrow(),
--
2.33.0

View File

@ -0,0 +1,75 @@
From f5299cda3a36ea68d248835db6733bbd14fd25cc Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Wed, 8 Nov 2023 16:55:29 +0800
Subject: [PATCH 051/103] fix(device): fix UT privilege error in ci
The user in ci has limited privileges, which will prevent actions
like writing some device sysattrs.
---
libs/device/src/device.rs | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/libs/device/src/device.rs b/libs/device/src/device.rs
index 284cd6e9..4f5779ce 100644
--- a/libs/device/src/device.rs
+++ b/libs/device/src/device.rs
@@ -3626,7 +3626,7 @@ G:devmaster
Q:devmaster
V:100
";
- touch_file("/tmp/tmp_db", false, None, None, None).unwrap();
+ touch_file("/tmp/tmp_db", false, Some(0o777), None, None).unwrap();
let mut f = OpenOptions::new().write(true).open("/tmp/tmp_db").unwrap();
f.write_all(content.as_bytes()).unwrap();
let device = Device::new();
@@ -3675,19 +3675,22 @@ V:100
}
unlink("/tmp/tmp_db").unwrap();
+ unlink("/tmp/tmp_db_writeonly").unwrap();
}
#[test]
fn test_set_is_initialized() {
let device = Device::from_subsystem_sysname("net", "lo").unwrap();
device.set_is_initialized();
- device
+ if device
.trigger_with_uuid(DeviceAction::Change, false)
- .unwrap();
- device
- .trigger_with_uuid(DeviceAction::Change, true)
- .unwrap();
- device.trigger(DeviceAction::Change).unwrap();
+ .is_ok()
+ {
+ device
+ .trigger_with_uuid(DeviceAction::Change, true)
+ .unwrap();
+ device.trigger(DeviceAction::Change).unwrap();
+ }
}
#[test]
@@ -3707,14 +3710,16 @@ V:100
device.set_devmode("666").unwrap();
device.set_diskseq("1").unwrap();
device.set_action_from_string("change").unwrap();
- device.set_sysattr_value("ifalias", Some("test")).unwrap();
+
+ if device.set_sysattr_value("ifalias", Some("test")).is_ok() {
+ assert_eq!(&device.get_cached_sysattr_value("ifalias").unwrap(), "test");
+ }
assert_eq!(&device.get_property_value("DEVUID").unwrap(), "1");
assert_eq!(&device.get_property_value("DEVGID").unwrap(), "1");
assert_eq!(&device.get_property_value("DEVMODE").unwrap(), "666");
assert_eq!(&device.get_property_value("DISKSEQ").unwrap(), "1");
assert_eq!(&device.get_property_value("ACTION").unwrap(), "change");
- assert_eq!(&device.get_cached_sysattr_value("ifalias").unwrap(), "test");
assert!(device.set_devuid("invalid").is_err());
assert!(device.set_devgid("invalid").is_err());
--
2.33.0

View File

@ -0,0 +1,28 @@
From 6188872fbc38cd38a3f2e909d9b4fe27473a8f67 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Tue, 21 Nov 2023 20:06:29 +0800
Subject: [PATCH 078/103] fix(device): keep consistent on the base path for db
cloned device object
The db cloned device object should collect data from the same base path with
the original device object.
---
libs/device/src/device.rs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libs/device/src/device.rs b/libs/device/src/device.rs
index b8507fe0..e8e2dcc5 100644
--- a/libs/device/src/device.rs
+++ b/libs/device/src/device.rs
@@ -2390,6 +2390,8 @@ impl Device {
pub fn shallow_clone(&self) -> Result<Device, Error> {
let device = Self::default();
+ device.set_base_path(self.base_path.borrow().as_str());
+
let syspath = self.get_syspath()?;
device.set_syspath(&syspath, false)?;
--
2.33.0

View File

@ -0,0 +1,26 @@
From 7c4bfcad52d1e8b2de7c6c2d5bfc1c08b401341f Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Wed, 8 Nov 2023 02:10:37 +0800
Subject: [PATCH 046/103] fix(device): replenish feature dependency of uuid on
basic crate
uuid is used on trigger_with_uuid method.
---
libs/device/Cargo.toml | 1 +
1 file changed, 1 insertion(+)
diff --git a/libs/device/Cargo.toml b/libs/device/Cargo.toml
index 6af6a404..ecb9955c 100644
--- a/libs/device/Cargo.toml
+++ b/libs/device/Cargo.toml
@@ -12,6 +12,7 @@ basic = { path = "../basic", default-features = false, features = [
"fs",
"fd",
"murmurhash2",
+ "uuid",
] }
event = { path = "../event" }
log = { path = "../log" }
--
2.33.0

View File

@ -0,0 +1,92 @@
From 400c6e270583c62724dd2bfd8b92ad96a2f0cfcb Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Wed, 8 Nov 2023 22:59:44 +0800
Subject: [PATCH 053/103] fix(device): set driver subsystem after generating
device from nulstr
The driver subsystem is omitted when receiving device object from nulstr,
which leads to incorrect device id in /run/devmaster/data/ for driver
subsystems.
---
libs/device/src/device.rs | 32 ++++++++++++++++++++++++++++---
libs/device/src/device_monitor.rs | 5 +++--
2 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/libs/device/src/device.rs b/libs/device/src/device.rs
index 4f5779ce..3845e21c 100644
--- a/libs/device/src/device.rs
+++ b/libs/device/src/device.rs
@@ -246,7 +246,29 @@ impl Device {
device.update_properties_bufs()?;
- Ok(device)
+ device.verify()
+ }
+
+ /// Verify the legality of a device object from nulstr.
+ fn verify(self) -> Result<Device, Error> {
+ if self.devpath.borrow().is_empty()
+ || self.subsystem.borrow().is_empty()
+ || *self.action.borrow() == DeviceAction::Invalid
+ || *self.seqnum.borrow() == 0
+ {
+ return Err(Error::Nix {
+ msg: "Received invalid device object from uevent".to_string(),
+ source: Errno::EINVAL,
+ });
+ }
+
+ if &*self.subsystem.borrow() == "drivers" {
+ self.set_drivers_subsystem()?;
+ }
+
+ self.sealed.replace(true);
+
+ Ok(self)
}
/// create a Device instance from devname
@@ -1237,7 +1259,7 @@ impl Device {
/// shadow clone a device object and import properties from db
pub fn clone_with_db(&self) -> Result<Device, Error> {
let device = self.shallow_clone()?;
- device.read_db()?;
+ device.read_db_internal(true)?;
device.sealed.replace(true);
Ok(device)
}
@@ -3535,9 +3557,13 @@ mod tests {
let syspath = dev.get_syspath().unwrap();
let devnum = dev.get_devnum().unwrap();
let id = dev.get_device_id().unwrap();
- let (nulstr, _) = dev.get_properties_nulstr().unwrap();
let devname = dev.get_devname().unwrap();
+ dev.set_action_from_string("change").unwrap();
+ dev.set_seqnum_from_string("1000").unwrap();
+
+ let (nulstr, _) = dev.get_properties_nulstr().unwrap();
+
let dev_new = Device::from_syspath(&syspath, true).unwrap();
assert_eq!(dev, &dev_new);
diff --git a/libs/device/src/device_monitor.rs b/libs/device/src/device_monitor.rs
index db51c40f..3f1d1ba6 100644
--- a/libs/device/src/device_monitor.rs
+++ b/libs/device/src/device_monitor.rs
@@ -249,8 +249,9 @@ mod tests {
///
fn dispatch(&self, e: &Events) -> i32 {
- let device = self.device_monitor.receive_device().unwrap();
- println!("{}", device.get_device_id().unwrap());
+ if let Ok(device) = self.device_monitor.receive_device() {
+ println!("{}", device.get_device_id().unwrap());
+ }
e.set_exit();
0
}
--
2.33.0

View File

@ -0,0 +1,138 @@
From 19d481dbf79337924cb0a389cb2e073e80ce5495 Mon Sep 17 00:00:00 2001
From: root <root@localhost.localdomain>
Date: Wed, 6 Dec 2023 20:53:59 +0800
Subject: [PATCH 1/1] loopdev
---
Cargo.lock | 1 +
exts/devmaster/Cargo.toml | 5 ++++-
libs/device/Cargo.toml | 6 ++++--
libs/device/src/device.rs | 9 +++++----
libs/device/src/utils.rs | 9 +++++++--
5 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index f103489..616a69c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -378,6 +378,7 @@ version = "0.5.1"
dependencies = [
"basic",
"bitflags",
+ "device",
"event",
"fnmatch-sys",
"libc",
diff --git a/exts/devmaster/Cargo.toml b/exts/devmaster/Cargo.toml
index c52e988..f9f2961 100644
--- a/exts/devmaster/Cargo.toml
+++ b/exts/devmaster/Cargo.toml
@@ -34,7 +34,7 @@ basic = { path = "../../libs/basic", default-features = false, features = [
"argv",
] }
blkid_rs = { path = "../../libs/blkid_rs" }
-device = { path = "../../libs/device" }
+device = { path = "../../libs/device", default-features = false }
event = { path = "../../libs/event" }
input_event_codes_rs = { path = "../../libs/input_event_codes_rs" }
kmod_rs = { path = "../../libs/kmod_rs" }
@@ -78,3 +78,6 @@ fnmatch-sys = "1.0.0"
[build-dependencies]
basic = { path = "../../libs/basic", features = ["cargo"] }
+
+[dev-dependencies]
+device = { path = "../../libs/device", features = ["loopdev"] }
diff --git a/libs/device/Cargo.toml b/libs/device/Cargo.toml
index ecb9955..1737c17 100644
--- a/libs/device/Cargo.toml
+++ b/libs/device/Cargo.toml
@@ -20,8 +20,7 @@ log = { path = "../log" }
# third libraries
bitflags = "1.3.2"
libc = { default-features = false, version = "0.2.140" }
-# only used in test case
-loopdev = "0.4.0"
+loopdev = { version = "0.4.0", optional = true } # only used in test case
nix = { default-features = false, version = "0.24", features = [
"ioctl",
"user",
@@ -32,3 +31,6 @@ nix = { default-features = false, version = "0.24", features = [
] }
snafu = { default-features = false, version = "0.7" }
fnmatch-sys = "1.0.0"
+
+[dev-dependencies]
+device = { path = ".", features = ["loopdev"] }
diff --git a/libs/device/src/device.rs b/libs/device/src/device.rs
index d1ab230..c11de5b 100644
--- a/libs/device/src/device.rs
+++ b/libs/device/src/device.rs
@@ -2845,16 +2845,17 @@ impl PartialEq for Device {
#[cfg(test)]
mod tests {
- use std::fs::OpenOptions;
- use std::panic::catch_unwind;
-
use crate::{
device::*,
device_enumerator::{DeviceEnumerationType, DeviceEnumerator},
- utils::LoopDev,
};
use basic::IN_SET;
use libc::S_IFBLK;
+ use std::fs::OpenOptions;
+ use std::panic::catch_unwind;
+
+ #[cfg(feature = "loopdev")]
+ use crate::utils::LoopDev;
fn compare(dev1: &Device, dev2: &Device) -> bool {
let syspath_1 = dev1.get_syspath().unwrap();
diff --git a/libs/device/src/utils.rs b/libs/device/src/utils.rs
index df750ed..2b814fa 100644
--- a/libs/device/src/utils.rs
+++ b/libs/device/src/utils.rs
@@ -11,12 +11,14 @@
// See the Mulan PSL v2 for more details.
//! utilities for device operation
+use crate::{error::*, Device};
use nix::errno::Errno;
+use std::{cmp::Ordering, fmt::Debug, fs::DirEntry, path::Path};
-use crate::{error::*, Device};
+#[cfg(feature = "loopdev")]
use loopdev::*;
+#[cfg(feature = "loopdev")]
use std::path::PathBuf;
-use std::{cmp::Ordering, fmt::Debug, fs::DirEntry, path::Path};
/// compare sound device
pub(crate) fn sound_device_compare(devpath_a: &str, devpath_b: &str) -> Ordering {
@@ -106,11 +108,13 @@ pub(crate) fn readlink_value<P: AsRef<Path> + Debug>(path: P) -> Result<String,
}
/// loop device
+#[cfg(feature = "loopdev")]
pub struct LoopDev {
tmpfile: String,
lodev: LoopDevice,
}
+#[cfg(feature = "loopdev")]
impl LoopDev {
/// create a temporate file with specific size
#[allow(dead_code)]
@@ -194,6 +198,7 @@ impl LoopDev {
}
}
+#[cfg(feature = "loopdev")]
impl Drop for LoopDev {
fn drop(&mut self) {
let _ = self.lodev.detach();
--
2.33.0

View File

@ -0,0 +1,27 @@
From 912387598bfaac6ad8a58e1810844daa27e0781e Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Fri, 17 Nov 2023 07:44:31 +0800
Subject: [PATCH 071/103] fix(devmaster): CONST can only take arch or virt as
attribute
The inverse operator '!' is missed previously.
---
exts/devmaster/src/lib/rules/rules_load.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/exts/devmaster/src/lib/rules/rules_load.rs b/exts/devmaster/src/lib/rules/rules_load.rs
index eee77e63..57ff19ac 100644
--- a/exts/devmaster/src/lib/rules/rules_load.rs
+++ b/exts/devmaster/src/lib/rules/rules_load.rs
@@ -832,7 +832,7 @@ impl RuleToken {
}
}
"CONST" => {
- if attr.is_none() || matches!(attr.as_ref().unwrap().as_str(), "arch" | "virt") {
+ if attr.is_none() || !matches!(attr.as_ref().unwrap().as_str(), "arch" | "virt") {
return Err(Error::RulesLoadError {
msg: "Key 'CONST' has invalid attribute.".location(&context),
});
--
2.33.0

View File

@ -0,0 +1,97 @@
From 26a93ec411098bf29fa8ebe9b84940f8c9455423 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Tue, 31 Oct 2023 20:24:30 +0800
Subject: [PATCH 014/103] fix(devmaster): adjust temporary file permissions
Adjust temporary file permissions.
---
exts/devmaster/src/lib/rules/node.rs | 10 +++++++++-
libs/device/src/device.rs | 22 +++++++++++++++++++---
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/exts/devmaster/src/lib/rules/node.rs b/exts/devmaster/src/lib/rules/node.rs
index 45b8b36b..9fba906e 100644
--- a/exts/devmaster/src/lib/rules/node.rs
+++ b/exts/devmaster/src/lib/rules/node.rs
@@ -33,7 +33,7 @@
//! directory, the directory will be removed.
use crate::{error::*, log_dev, log_dev_option};
-use basic::fs_util::path_simplify;
+use basic::fs_util::{chmod, path_simplify};
use basic::fs_util::{fchmod_and_chown, futimens_opath, symlink};
use basic::{fd_util::xopendirat, fs_util::remove_dir_until};
use cluFlock::ExclusiveFlock;
@@ -355,6 +355,14 @@ pub(crate) fn open_prior_dir(symlink: &str) -> Result<(Dir, File)> {
})
.log_error(&format!("failed to create directory all '{}'", dirname))?;
+ if let Err(e) = chmod(dirname.as_str(), 0o750) {
+ log::error!("Failed to set permission for {}: {}", &dirname, e);
+ }
+
+ if let Err(e) = chmod("/run/devmaster/links", 0o750) {
+ log::error!("Failed to set permission for /run/devmaster/links: {}", e);
+ }
+
let dir = nix::dir::Dir::from_fd(
nix::fcntl::open(
dirname.as_str(),
diff --git a/libs/device/src/device.rs b/libs/device/src/device.rs
index 5b1eff1f..5a95e0f5 100644
--- a/libs/device/src/device.rs
+++ b/libs/device/src/device.rs
@@ -15,7 +15,7 @@
use crate::err_wrapper;
use crate::utils::readlink_value;
use crate::{error::*, DeviceAction};
-use basic::fs_util::{open_temporary, touch_file};
+use basic::fs_util::{chmod, open_temporary, touch_file};
use basic::parse::{device_path_parse_devnum, parse_devnum, parse_ifindex};
use libc::{
dev_t, faccessat, gid_t, mode_t, uid_t, F_OK, S_IFBLK, S_IFCHR, S_IFDIR, S_IFLNK, S_IFMT,
@@ -1532,6 +1532,10 @@ impl Device {
.map_or_else(|| nix::Error::EIO, nix::Error::from_i32),
})?;
+ if let Err(e) = chmod(DB_BASE_DIR, 0o750) {
+ log::error!("Failed to set permission for /run/devmaster/data/: {}", e);
+ }
+
let (mut file, tmp_file) = open_temporary(&db_path).map_err(|e| {
let errno = match e {
basic::error::Error::Nix { source } => source,
@@ -1546,9 +1550,9 @@ impl Device {
fchmod(
file.as_raw_fd(),
if *self.db_persist.borrow() {
- Mode::from_bits(0o1644).unwrap()
+ Mode::from_bits(0o1640).unwrap()
} else {
- Mode::from_bits(0o644).unwrap()
+ Mode::from_bits(0o640).unwrap()
},
)
.map_err(|e| {
@@ -1697,6 +1701,18 @@ impl Device {
source: nix::Error::EINVAL,
})?;
+ if let Err(e) = chmod(TAGS_BASE_DIR, 0o750) {
+ log::error!("Failed to set permission for {}: {}", TAGS_BASE_DIR, e);
+ }
+
+ if let Err(e) = chmod(&format!("{}{}", TAGS_BASE_DIR, tag), 0o750) {
+ log::error!(
+ "Failed to set permission for {}: {}",
+ format!("{}{}", TAGS_BASE_DIR, tag),
+ e
+ );
+ }
+
return Ok(());
}
--
2.33.0

View File

@ -0,0 +1,27 @@
From 498398f0b59824726a9bc0bbc4c53af5c8b7b4a2 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Thu, 2 Nov 2023 18:14:40 +0800
Subject: [PATCH 021/103] fix(devmaster): append zero to the file name
The file name is transferred to 'faccessat', which should be a C
like string that ends with zero.
---
exts/devmaster/src/lib/builtin/net_id.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/exts/devmaster/src/lib/builtin/net_id.rs b/exts/devmaster/src/lib/builtin/net_id.rs
index 2b2cc59b..e5f1faa6 100644
--- a/exts/devmaster/src/lib/builtin/net_id.rs
+++ b/exts/devmaster/src/lib/builtin/net_id.rs
@@ -401,7 +401,7 @@ fn parse_hotplug_slot_from_function_id(
});
}
- let filename = format!("{:08}", function_id);
+ let filename = format!("{:08}\0", function_id);
if unsafe { faccessat(slots_dirfd, filename.as_ptr() as *const c_char, F_OK, 0) } < 0 {
log_dev!(
--
2.33.0

View File

@ -0,0 +1,265 @@
From ecab786d75eaf3ab6a110f1d6b47c1b1d7e2ec01 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Tue, 21 Nov 2023 15:17:23 +0800
Subject: [PATCH 076/103] fix(devmaster): avoid potential test case failures
Sharing the same temporary rules directory in multiple test cases
may lead to weird and occasional failures.
---
exts/devmaster/src/lib/rules/rules_load.rs | 123 ++++++++++++---------
1 file changed, 69 insertions(+), 54 deletions(-)
diff --git a/exts/devmaster/src/lib/rules/rules_load.rs b/exts/devmaster/src/lib/rules/rules_load.rs
index e9dd2259..999c9692 100644
--- a/exts/devmaster/src/lib/rules/rules_load.rs
+++ b/exts/devmaster/src/lib/rules/rules_load.rs
@@ -1736,14 +1736,24 @@ mod tests {
use std::panic::catch_unwind;
use std::{fs, path::Path};
- fn create_tmp_rules(dir: &'static str, file: &str, content: &str) {
+ fn create_tmp_rules(dir: &'static str, file: &str, content: &str, truncate: bool) {
assert!(fs::create_dir_all(dir).is_ok());
- assert!(fs::write(format!("{}/{}", dir, file), content,).is_ok());
+ let s = format!("{}/{}", dir, file);
+ let p = Path::new(&s);
+ assert!(fs::write(p, content,).is_ok());
+ let mut f = fs::OpenOptions::new()
+ .write(true)
+ .truncate(truncate)
+ .open(p)
+ .unwrap();
+ f.write_all(content.as_bytes()).unwrap();
+ f.flush().unwrap();
+ while !p.exists() {}
}
fn clear_tmp_rules(dir: &'static str) {
if Path::new(dir).exists() {
- assert!(fs::remove_dir_all(dir).is_ok());
+ fs::remove_dir_all(dir).unwrap();
}
}
@@ -1758,7 +1768,7 @@ mod tests {
0,
false,
);
- clear_tmp_rules("/tmp/devmaster/rules");
+ clear_tmp_rules("/tmp/devmaster/test_load_rules");
let legal_rule = vec![
"ACTION == \"change\", SYMLINK += \"test1\"", // Test legal rules.
@@ -1810,23 +1820,21 @@ mod tests {
"SECLABEL{x}:=\"$hello\"", // Illegal placeholder in value will throw warning rather than panic.
];
- create_tmp_rules("/tmp/devmaster/rules", "00-test.rules", "");
-
for &content in legal_rule.iter() {
- let mut f = fs::OpenOptions::new()
- .write(true)
- .truncate(true)
- .open("/tmp/devmaster/rules/00-test.rules")
- .unwrap();
- f.write_all(content.as_bytes()).unwrap();
+ create_tmp_rules(
+ "/tmp/devmaster/test_load_rules",
+ "00-test.rules",
+ content,
+ true,
+ );
let _ = Rules::load_rules(
- vec!["/tmp/devmaster/rules".to_string()],
+ vec!["/tmp/devmaster/test_load_rules".to_string()],
ResolveNameTime::Early,
);
}
- clear_tmp_rules("/tmp/devmaster/rules");
+ clear_tmp_rules("/tmp/devmaster/test_load_rules");
}
#[test]
@@ -1840,7 +1848,7 @@ mod tests {
0,
false,
);
- clear_tmp_rules("/tmp/devmaster/rules");
+ clear_tmp_rules("/tmp/devmaster/test_load_rules_panic");
let illegal_rule = vec![
"action==\"change\"", // Error in State::Pre
@@ -1945,26 +1953,24 @@ mod tests {
"XXX=\"xxx\"", // Invalid token key.
];
- create_tmp_rules("/tmp/devmaster/rules", "00-test.rules", "");
-
for content in illegal_rule.iter() {
- let mut f = fs::OpenOptions::new()
- .write(true)
- .truncate(true)
- .open("/tmp/devmaster/rules/00-test.rules")
- .unwrap();
- f.write_all(content.as_bytes()).unwrap();
+ create_tmp_rules(
+ "/tmp/devmaster/test_load_rules_panic",
+ "00-test.rules",
+ content,
+ true,
+ );
assert!(catch_unwind(|| {
let _ = Rules::load_rules(
- vec!["/tmp/devmaster/rules".to_string()],
+ vec!["/tmp/devmaster/test_load_rules_panic".to_string()],
ResolveNameTime::Early,
);
})
.is_err());
}
- clear_tmp_rules("/tmp/devmaster/rules");
+ clear_tmp_rules("/tmp/devmaster/test_load_rules_panic");
}
#[test]
@@ -1978,50 +1984,48 @@ mod tests {
0,
false,
);
- clear_tmp_rules("/tmp/devmaster/rules");
+ clear_tmp_rules("/tmp/devmaster/test_resolve_name_time");
let legal = vec!["OWNER=\"root\"", "GROUP=\"root\""];
let illegal = vec!["OWNER=\"xxxx\"", "GROUP=\"xxxx\""];
- create_tmp_rules("/tmp/devmaster/rules", "00-test.rules", "");
-
for &content in legal.iter() {
- let mut f = fs::OpenOptions::new()
- .write(true)
- .truncate(true)
- .open("/tmp/devmaster/rules/00-test.rules")
- .unwrap();
- f.write_all(content.as_bytes()).unwrap();
+ create_tmp_rules(
+ "/tmp/devmaster/test_resolve_name_time",
+ "00-test.rules",
+ content,
+ true,
+ );
let _ = Rules::load_rules(
- vec!["/tmp/devmaster/rules".to_string()],
+ vec!["/tmp/devmaster/test_resolve_name_time".to_string()],
ResolveNameTime::Early,
);
}
for &content in illegal.iter() {
- let mut f = fs::OpenOptions::new()
- .write(true)
- .truncate(true)
- .open("/tmp/devmaster/rules/00-test.rules")
- .unwrap();
- f.write_all(content.as_bytes()).unwrap();
+ create_tmp_rules(
+ "/tmp/devmaster/test_resolve_name_time",
+ "00-test.rules",
+ content,
+ true,
+ );
let _ = Rules::load_rules(
- vec!["/tmp/devmaster/rules".to_string()],
+ vec!["/tmp/devmaster/test_resolve_name_time".to_string()],
ResolveNameTime::Late,
);
assert!(catch_unwind(|| {
let _ = Rules::load_rules(
- vec!["/tmp/devmaster/rules".to_string()],
+ vec!["/tmp/devmaster/test_resolve_name_time".to_string()],
ResolveNameTime::Early,
);
})
.is_err());
}
- clear_tmp_rules("/tmp/devmaster/rules");
+ clear_tmp_rules("/tmp/devmaster/test_resolve_name_time");
}
#[test]
@@ -2330,11 +2334,11 @@ mod tests {
#[test]
fn test_parse_rules() {
- create_dir_all("/tmp/devmaster/rules").unwrap();
+ create_dir_all("/tmp/devmaster/test_parse_rules").unwrap();
/* Normal rule file. */
touch_file(
- "/tmp/devmaster/rules/00-a.rules",
+ "/tmp/devmaster/test_parse_rules/00-a.rules",
false,
Some(0o777),
None,
@@ -2342,10 +2346,17 @@ mod tests {
)
.unwrap();
/* Skip parsing the file with invalid suffix. */
- touch_file("/tmp/devmaster/rules/01-b", false, Some(0o777), None, None).unwrap();
+ touch_file(
+ "/tmp/devmaster/test_parse_rules/01-b",
+ false,
+ Some(0o777),
+ None,
+ None,
+ )
+ .unwrap();
/* Failed to parse the file as it is not readable. */
touch_file(
- "/tmp/devmaster/rules/02-c.rules",
+ "/tmp/devmaster/test_parse_rules/02-c.rules",
false,
Some(0o000),
None,
@@ -2354,21 +2365,25 @@ mod tests {
.unwrap();
let rules = Arc::new(RwLock::new(Rules::new(
- vec!["/tmp/devmaster/rules".to_string()],
+ vec!["/tmp/devmaster/test_parse_rules".to_string()],
ResolveNameTime::Never,
)));
- // Rules::parse_rules(Arc::new(RwLock::new(rules)));
-
- RuleFile::load_file("/tmp/devmaster/rules/00-a.rules".to_string(), rules.clone());
+ RuleFile::load_file(
+ "/tmp/devmaster/test_parse_rules/00-a.rules".to_string(),
+ rules.clone(),
+ );
if nix::unistd::getuid().as_raw() != 0 {
assert!(catch_unwind(|| {
- RuleFile::load_file("/tmp/devmaster/rules/02-c.rules".to_string(), rules.clone());
+ RuleFile::load_file(
+ "/tmp/devmaster/test_parse_rules/02-c.rules".to_string(),
+ rules.clone(),
+ );
})
.is_err());
}
- remove_dir_all("/tmp/devmaster").unwrap();
+ remove_dir_all("/tmp/devmaster/test_parse_rules").unwrap();
}
}
--
2.33.0

View File

@ -0,0 +1,64 @@
From 0ee8078d05e8fd67251b20383fc5b3cf04aedfb1 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Fri, 17 Nov 2023 01:20:21 +0800
Subject: [PATCH 069/103] fix(devmaster): cache the parsed user and group
The previously parsed user and group should be cached to avoid repeatedly
parsed later. Also fix and open the corresponding test case that is ignored
previously.
---
exts/devmaster/src/lib/rules/rules_load.rs | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/exts/devmaster/src/lib/rules/rules_load.rs b/exts/devmaster/src/lib/rules/rules_load.rs
index 19b7aaa4..a4535b52 100644
--- a/exts/devmaster/src/lib/rules/rules_load.rs
+++ b/exts/devmaster/src/lib/rules/rules_load.rs
@@ -133,7 +133,10 @@ impl Rules {
match User::from_name(username) {
Ok(user) => match user {
- Some(u) => Ok(u),
+ Some(u) => {
+ self.users.insert(username.to_string(), u.clone());
+ Ok(u)
+ }
None => Err(Error::RulesLoadError {
msg: format!("The user name {} has no credential.", username),
}),
@@ -152,7 +155,10 @@ impl Rules {
match Group::from_name(groupname) {
Ok(group) => match group {
- Some(g) => Ok(g),
+ Some(g) => {
+ self.groups.insert(groupname.to_string(), g.clone());
+ Ok(g)
+ }
None => Err(Error::RulesLoadError {
msg: format!("The group name {} has no credential.", groupname),
}),
@@ -1983,14 +1989,15 @@ SYMLINK += \"test111111\"",
}
#[test]
- #[ignore]
- fn test_resolve_user() {
+ fn test_resolve_user_group() {
let mut rules = Rules::new(vec![], ResolveNameTime::Early);
- assert!(rules.resolve_user("tss").is_ok());
assert!(rules.resolve_user("root").is_ok());
- assert!(rules.users.contains_key("tss"));
assert!(rules.users.contains_key("root"));
- assert!(rules.resolve_user("cjy").is_err());
+ assert!(rules.resolve_user("abcdefg").is_err());
+
+ assert!(rules.resolve_group("root").is_ok());
+ assert!(rules.groups.contains_key("root"));
+ assert!(rules.resolve_group("abcdefg").is_err());
}
#[test]
--
2.33.0

View File

@ -0,0 +1,123 @@
From f923eda87854adb2d245f43ba3656b0fb46fe7c1 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Fri, 3 Nov 2023 01:47:16 +0800
Subject: [PATCH 028/103] fix(devmaster): check the validity of kmod context
during new method
The kmod_sys::kmod_new may return a null pointer. Check the validity
of the pointer before using it to constuct the kmod instance.
---
exts/devmaster/src/lib/builtin/kmod.rs | 21 +++++++++++++++++----
libs/kmod_rs/src/lib.rs | 17 ++++++++---------
2 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/exts/devmaster/src/lib/builtin/kmod.rs b/exts/devmaster/src/lib/builtin/kmod.rs
index ac73d1bb..cf718d41 100644
--- a/exts/devmaster/src/lib/builtin/kmod.rs
+++ b/exts/devmaster/src/lib/builtin/kmod.rs
@@ -24,14 +24,14 @@ use std::rc::Rc;
/// kmod builtin command
pub(crate) struct Kmod {
/// kmod struct
- kernel_module: Rc<RefCell<kmod_rs::LibKmod>>,
+ kernel_module: Option<Rc<RefCell<kmod_rs::LibKmod>>>,
}
impl Kmod {
/// create Kmod
pub(crate) fn new() -> Kmod {
Kmod {
- kernel_module: Rc::new(RefCell::new(kmod_rs::LibKmod::new())),
+ kernel_module: kmod_rs::LibKmod::new().map(|inner| Rc::new(RefCell::new(inner))),
}
}
}
@@ -53,7 +53,8 @@ impl Builtin for Kmod {
) -> Result<bool> {
let device = exec_unit.get_device();
- if self.kernel_module.borrow().is_ctx_null() {
+ if self.kernel_module.is_none() {
+ log::error!("Kmod context is not loaded.");
return Ok(true);
}
@@ -72,6 +73,8 @@ impl Builtin for Kmod {
if !modalias.is_empty() {
if let Err(e) = self
.kernel_module
+ .as_ref()
+ .unwrap()
.borrow_mut()
.module_load_and_warn(&modalias, false)
{
@@ -82,6 +85,8 @@ impl Builtin for Kmod {
for i in 2..argc {
if let Err(e) = self
.kernel_module
+ .as_ref()
+ .unwrap()
.borrow_mut()
.module_load_and_warn(&argv[i as usize], false)
{
@@ -94,7 +99,13 @@ impl Builtin for Kmod {
/// builtin init function
fn init(&self) {
- if let Err(e) = self.kernel_module.borrow_mut().load_resources() {
+ if let Err(e) = self
+ .kernel_module
+ .as_ref()
+ .unwrap()
+ .borrow_mut()
+ .load_resources()
+ {
log::error!("Load resources failed! {}", e);
}
}
@@ -105,6 +116,8 @@ impl Builtin for Kmod {
/// check whether builtin command should reload
fn should_reload(&self) -> bool {
self.kernel_module
+ .as_ref()
+ .unwrap()
.borrow_mut()
.validate_resources()
.map_or(false, |e| {
diff --git a/libs/kmod_rs/src/lib.rs b/libs/kmod_rs/src/lib.rs
index d0efabc5..f95cd32a 100644
--- a/libs/kmod_rs/src/lib.rs
+++ b/libs/kmod_rs/src/lib.rs
@@ -73,21 +73,20 @@ impl Drop for LibKmod {
}
}
-impl Default for LibKmod {
- fn default() -> Self {
- Self::new()
- }
-}
-
impl LibKmod {
/// Create libkmod
- pub fn new() -> LibKmod {
+ pub fn new() -> Option<LibKmod> {
let c = unsafe { kmod_sys::kmod_new(std::ptr::null(), std::ptr::null()) };
- LibKmod {
+
+ if c.is_null() {
+ return None;
+ }
+
+ Some(LibKmod {
ctx: c,
kmod_list_head: ptr::null::<kmod_sys::kmod_list>() as *mut kmod_sys::kmod_list,
module: ptr::null::<kmod_sys::kmod_module>() as *mut kmod_sys::kmod_module,
- }
+ })
}
/// Create KmodListIter with internal members
--
2.33.0

View File

@ -0,0 +1,31 @@
From adf0de497132a30577cd38c6a9e0079c5224c279 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Fri, 17 Nov 2023 06:12:36 +0800
Subject: [PATCH 070/103] fix(devmaster): drop incorrect preventation on
removal op for SYMLINK token
The preventation code makes the rules loading panic when SYMLINK takes
the removal assignment op, which is incorrect.
---
exts/devmaster/src/lib/rules/rules_load.rs | 5 -----
1 file changed, 5 deletions(-)
diff --git a/exts/devmaster/src/lib/rules/rules_load.rs b/exts/devmaster/src/lib/rules/rules_load.rs
index a4535b52..eee77e63 100644
--- a/exts/devmaster/src/lib/rules/rules_load.rs
+++ b/exts/devmaster/src/lib/rules/rules_load.rs
@@ -693,11 +693,6 @@ impl RuleToken {
msg: "Key 'SYMLINK' can not carry attribute.".location(&context),
});
}
- if op == OperatorType::Remove {
- return Err(Error::RulesLoadError {
- msg: "Key 'SYMLINK' can not take remove operator.".location(&context),
- });
- }
if !op_is_match {
if let Err(e) = check_value_format(key.as_str(), value.as_str(), false) {
--
2.33.0

View File

@ -0,0 +1,107 @@
From 4c23e696a6bbf19f4f0806501af04aaf606ab3fa Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Wed, 8 Nov 2023 14:28:35 +0800
Subject: [PATCH 050/103] fix(devmaster): drop unnecessary debug trait
implementations
The debug trait derivations will break the compilation.
---
.../src/lib/framework/control_manager.rs | 1 -
.../src/lib/framework/garbage_collect.rs | 2 --
.../src/lib/framework/worker_manager.rs | 2 --
libs/device/src/error.rs | 16 +++-------------
4 files changed, 3 insertions(+), 18 deletions(-)
diff --git a/exts/devmaster/src/lib/framework/control_manager.rs b/exts/devmaster/src/lib/framework/control_manager.rs
index 75fae984..342c6a0c 100644
--- a/exts/devmaster/src/lib/framework/control_manager.rs
+++ b/exts/devmaster/src/lib/framework/control_manager.rs
@@ -30,7 +30,6 @@ use std::{
pub const CONTROL_MANAGER_LISTEN_ADDR: &str = "/run/devmaster/control";
/// control manager
-#[derive(Debug)]
pub struct ControlManager {
/// listener for devctl messages
listener: RefCell<UnixListener>,
diff --git a/exts/devmaster/src/lib/framework/garbage_collect.rs b/exts/devmaster/src/lib/framework/garbage_collect.rs
index 7a12ede8..c154f430 100644
--- a/exts/devmaster/src/lib/framework/garbage_collect.rs
+++ b/exts/devmaster/src/lib/framework/garbage_collect.rs
@@ -25,7 +25,6 @@ use std::{
/// max time interval for idle worker
const WORKER_MAX_IDLE_INTERVAL: u64 = 3;
-#[derive(Debug)]
pub(crate) struct GarbageCollect {
devmaster: Weak<RefCell<Devmaster>>,
@@ -128,7 +127,6 @@ impl Source for GarbageCollect {
}
/// kill idle workers
-#[derive(Debug)]
pub(crate) struct IdleWorkerKiller {
/// time interval
pub(crate) time: u64,
diff --git a/exts/devmaster/src/lib/framework/worker_manager.rs b/exts/devmaster/src/lib/framework/worker_manager.rs
index c7c1d45f..870f6779 100644
--- a/exts/devmaster/src/lib/framework/worker_manager.rs
+++ b/exts/devmaster/src/lib/framework/worker_manager.rs
@@ -47,7 +47,6 @@ pub(crate) enum WorkerMessage {
}
/// worker manager
-#[derive(Debug)]
pub struct WorkerManager {
/// max number of workers
pub(crate) workers_capacity: u32,
@@ -65,7 +64,6 @@ pub struct WorkerManager {
}
/// worker
-#[derive(Debug)]
pub struct Worker {
/// worker unique id
id: u32,
diff --git a/libs/device/src/error.rs b/libs/device/src/error.rs
index 10410301..2cea6f4b 100644
--- a/libs/device/src/error.rs
+++ b/libs/device/src/error.rs
@@ -19,22 +19,13 @@ use snafu::prelude::Snafu;
#[derive(Debug, Snafu)]
#[snafu(visibility(pub))]
#[non_exhaustive]
+#[allow(missing_docs)]
pub enum Error {
- /// other error
#[snafu(context, display("Device error: {}", msg))]
- Nix {
- /// message
- msg: String,
- /// errno indicates the error kind
- source: nix::Error,
- },
+ Nix { msg: String, source: nix::Error },
#[snafu(context, display("IO error: {}", msg))]
- Io {
- /// message
- msg: String,
- source: std::io::Error,
- },
+ Io { msg: String, source: std::io::Error },
#[snafu(context, display("Basic error: {}", msg))]
Basic { msg: String, source: basic::Error },
@@ -106,7 +97,6 @@ impl Error {
}
}
-
#[cfg(test)]
mod test {
use super::*;
--
2.33.0

View File

@ -0,0 +1,35 @@
From f309964ae6101b94b2dd3c90f6e363e175685301 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Fri, 3 Nov 2023 01:11:39 +0800
Subject: [PATCH 027/103] fix(devmaster): fix misspelt sysattr sas_address
The 'sas_address' attribte is misspelt.
---
exts/devmaster/src/lib/builtin/path_id.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/exts/devmaster/src/lib/builtin/path_id.rs b/exts/devmaster/src/lib/builtin/path_id.rs
index ecd730f8..303b7528 100644
--- a/exts/devmaster/src/lib/builtin/path_id.rs
+++ b/exts/devmaster/src/lib/builtin/path_id.rs
@@ -390,7 +390,7 @@ impl PathId {
Err(_) => return None,
};
- let sas_address = match asadev.get_sysattr_value("asa_address") {
+ let sas_address = match asadev.get_sysattr_value("sas_address") {
Ok(addr) => addr,
Err(_) => return None,
};
@@ -430,7 +430,7 @@ impl PathId {
Err(_) => return None,
};
- let target = match sessiondev.get_sysattr_value("asa_address") {
+ let target = match sessiondev.get_sysattr_value("sas_address") {
Ok(port) => port,
Err(_) => return None,
};
--
2.33.0

View File

@ -0,0 +1,27 @@
From 84d4b4fcf0b2809e1857be3c17099ba1c41d7ea7 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Thu, 2 Nov 2023 21:44:50 +0800
Subject: [PATCH 023/103] fix(devmaster): fix out-of-bounds in net_id
The pci subclass consists of two numbers, but is captured with three
length by mistake.
---
exts/devmaster/src/lib/builtin/net_id.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/exts/devmaster/src/lib/builtin/net_id.rs b/exts/devmaster/src/lib/builtin/net_id.rs
index e5f1faa6..091d6ccd 100644
--- a/exts/devmaster/src/lib/builtin/net_id.rs
+++ b/exts/devmaster/src/lib/builtin/net_id.rs
@@ -338,7 +338,7 @@ fn is_pci_bridge(dev: Rc<RefCell<Device>>) -> bool {
/* PCI device subclass 04 corresponds to PCI bridge */
// modalias[idx+2:2
- let pci_subclass = match modalias.get(idx + 2..idx + 5) {
+ let pci_subclass = match modalias.get(idx + 2..idx + 4) {
Some(s) => s,
None => return false,
};
--
2.33.0

View File

@ -0,0 +1,28 @@
From f57218f2439ec7f0920af7f9e446ce3449944c7c Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Thu, 2 Nov 2023 19:47:28 +0800
Subject: [PATCH 022/103] fix(devmaster): fix potential integer overflow in
scsi_id
The buffer is a u8 vector, whose element may overflow if it add 4
before changing type to usize.
---
exts/devmaster/src/bin/tools/scsi_id/main.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/exts/devmaster/src/bin/tools/scsi_id/main.rs b/exts/devmaster/src/bin/tools/scsi_id/main.rs
index 8098c8bf..0e621cd3 100644
--- a/exts/devmaster/src/bin/tools/scsi_id/main.rs
+++ b/exts/devmaster/src/bin/tools/scsi_id/main.rs
@@ -1158,7 +1158,7 @@ fn do_scsi_page80_inquiry(
return 1;
}
- let len: usize = (buffer[3] + 4) as usize;
+ let len: usize = buffer[3] as usize + 4;
if get_serial {
dev_scsi.serial = "S".to_string();
--
2.33.0

View File

@ -0,0 +1,43 @@
From 9f50a5627a9cfb9b6dba4eeaa524d8986f2408b8 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Mon, 30 Oct 2023 20:58:53 +0800
Subject: [PATCH 008/103] fix(devmaster): keep the same name with udev control
socket
The libudev api will check the /run/udev/control socket to indicate
wether udevd is running. Keep the name of control socket same with
udev.
---
exts/devmaster/src/lib/framework/control_manager.rs | 2 +-
exts/devmaster/src/lib/framework/worker_manager.rs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/exts/devmaster/src/lib/framework/control_manager.rs b/exts/devmaster/src/lib/framework/control_manager.rs
index 38c7c337..75fae984 100644
--- a/exts/devmaster/src/lib/framework/control_manager.rs
+++ b/exts/devmaster/src/lib/framework/control_manager.rs
@@ -27,7 +27,7 @@ use std::{
};
/// listening address for control manager
-pub const CONTROL_MANAGER_LISTEN_ADDR: &str = "/run/devmaster/control.sock";
+pub const CONTROL_MANAGER_LISTEN_ADDR: &str = "/run/devmaster/control";
/// control manager
#[derive(Debug)]
diff --git a/exts/devmaster/src/lib/framework/worker_manager.rs b/exts/devmaster/src/lib/framework/worker_manager.rs
index 55778ddb..c7c1d45f 100644
--- a/exts/devmaster/src/lib/framework/worker_manager.rs
+++ b/exts/devmaster/src/lib/framework/worker_manager.rs
@@ -38,7 +38,7 @@ use std::{
use super::devmaster::Devmaster;
/// worker manager listen address
-pub const WORKER_MANAGER_LISTEN_ADDR: &str = "/run/devmaster/worker.sock";
+pub const WORKER_MANAGER_LISTEN_ADDR: &str = "/run/devmaster/worker";
/// messages sended by manager to workers
pub(crate) enum WorkerMessage {
--
2.33.0

View File

@ -0,0 +1,26 @@
From 0df31891bfd0ab047d29afbd2313bd98bcf69a98 Mon Sep 17 00:00:00 2001
From: huyubiao <huyubiao@huawei.com>
Date: Mon, 6 Nov 2023 20:13:11 +0800
Subject: [PATCH 033/103] fix: return Ok when the .hwdb and hwdb.bin files
cannot be found
---
libs/hwdb/src/hwdb_util.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libs/hwdb/src/hwdb_util.rs b/libs/hwdb/src/hwdb_util.rs
index 2ff6243a..a5c2eac0 100644
--- a/libs/hwdb/src/hwdb_util.rs
+++ b/libs/hwdb/src/hwdb_util.rs
@@ -753,7 +753,7 @@ impl HwdbUtil {
hwdb_bin
),
Err(e) => {
- if e == nix::Error::ENOENT {
+ if e != nix::Error::ENOENT {
log::error!(
"Failed to remove compiled hwdb database {:?}:{:?}",
hwdb_bin,
--
2.33.0

View File

@ -0,0 +1,68 @@
From a01bde892736601aa57a2780e45b00cdb842dc16 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Thu, 16 Nov 2023 10:05:37 +0800
Subject: [PATCH 065/103] refactor(devmaster): compress unnecessary code
Eliminate unnecessary code for error handling.
---
.../src/lib/framework/uevent_monitor.rs | 32 ++++---------------
1 file changed, 6 insertions(+), 26 deletions(-)
diff --git a/exts/devmaster/src/lib/framework/uevent_monitor.rs b/exts/devmaster/src/lib/framework/uevent_monitor.rs
index 809071d1..30bbd570 100644
--- a/exts/devmaster/src/lib/framework/uevent_monitor.rs
+++ b/exts/devmaster/src/lib/framework/uevent_monitor.rs
@@ -12,12 +12,9 @@
//! uevent_monitor
//!
-use crate::error::*;
use crate::framework::job_queue::JobQueue;
use device::device_monitor::{DeviceMonitor, MonitorNetlinkGroup};
use event::{EventType, Events, Source};
-use nix::errno::Errno;
-use snafu::ResultExt;
use std::os::unix::io::RawFd;
use std::rc::Rc;
@@ -71,31 +68,14 @@ impl Source for UeventMonitor {
fn dispatch(&self, _: &Events) -> i32 {
let device = match self.device_monitor.receive_device() {
Ok(ret) => ret,
- Err(e) => match e {
- device::error::Error::Nix {
- msg: _,
- source: Errno::EAGAIN,
- } => {
- return 0;
- }
- device::error::Error::Nix { msg: _, source: _ } => {
- log::error!("{}", e);
- return 0;
- }
- _ => {
- return 0;
- }
- },
+ Err(e) => {
+ log::error!("Monitor Error: {}", e);
+ return 0;
+ }
};
- log::debug!(
- "Monitor: received device {}",
- device
- .get_devpath()
- .context(DeviceSnafu)
- .log_error("uevent has no devpath")
- .unwrap_or_default()
- );
+ /* The devpath is guaranteed to be valid. */
+ log::debug!("Monitor: received device {}", device.get_devpath().unwrap());
self.job_queue.job_queue_insert(device);
0
--
2.33.0

View File

@ -0,0 +1,73 @@
From 2fa2b67a81b6bbb1af175703bf00ebf990bac026 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Tue, 21 Nov 2023 20:02:49 +0800
Subject: [PATCH 077/103] refactor(devmaster): rename the create_tmp_rules
function to create_tmp_file
The function is used to create a temporary file and write content inside it.
It is more proper to have a more general name.
---
exts/devmaster/src/lib/rules/rules_load.rs | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/exts/devmaster/src/lib/rules/rules_load.rs b/exts/devmaster/src/lib/rules/rules_load.rs
index 999c9692..b035f562 100644
--- a/exts/devmaster/src/lib/rules/rules_load.rs
+++ b/exts/devmaster/src/lib/rules/rules_load.rs
@@ -1724,7 +1724,7 @@ impl RuleToken {
}
#[cfg(test)]
-mod tests {
+pub(crate) mod tests {
use basic::fs_util::touch_file;
use log::init_log;
use log::Level;
@@ -1736,7 +1736,7 @@ mod tests {
use std::panic::catch_unwind;
use std::{fs, path::Path};
- fn create_tmp_rules(dir: &'static str, file: &str, content: &str, truncate: bool) {
+ pub(crate) fn create_tmp_file(dir: &'static str, file: &str, content: &str, truncate: bool) {
assert!(fs::create_dir_all(dir).is_ok());
let s = format!("{}/{}", dir, file);
let p = Path::new(&s);
@@ -1821,7 +1821,7 @@ mod tests {
];
for &content in legal_rule.iter() {
- create_tmp_rules(
+ create_tmp_file(
"/tmp/devmaster/test_load_rules",
"00-test.rules",
content,
@@ -1954,7 +1954,7 @@ mod tests {
];
for content in illegal_rule.iter() {
- create_tmp_rules(
+ create_tmp_file(
"/tmp/devmaster/test_load_rules_panic",
"00-test.rules",
content,
@@ -1990,7 +1990,7 @@ mod tests {
let illegal = vec!["OWNER=\"xxxx\"", "GROUP=\"xxxx\""];
for &content in legal.iter() {
- create_tmp_rules(
+ create_tmp_file(
"/tmp/devmaster/test_resolve_name_time",
"00-test.rules",
content,
@@ -2004,7 +2004,7 @@ mod tests {
}
for &content in illegal.iter() {
- create_tmp_rules(
+ create_tmp_file(
"/tmp/devmaster/test_resolve_name_time",
"00-test.rules",
content,
--
2.33.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,75 @@
From c600ca109d74c38f130b84353b6f21ff2439a36d Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Wed, 15 Nov 2023 15:35:26 +0800
Subject: [PATCH 062/103] test(device): add UT for device monitor
---
libs/device/src/device_monitor.rs | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/libs/device/src/device_monitor.rs b/libs/device/src/device_monitor.rs
index 3f1d1ba6..c6ad3ec6 100644
--- a/libs/device/src/device_monitor.rs
+++ b/libs/device/src/device_monitor.rs
@@ -216,7 +216,7 @@ impl Drop for DeviceMonitor {
#[cfg(test)]
mod tests {
use super::*;
- use crate::device::*;
+ use crate::{device::*, DeviceAction};
use event::*;
use std::{os::unix::prelude::RawFd, rc::Rc, thread::spawn};
@@ -264,9 +264,13 @@ mod tests {
}
/// test whether device monitor can receive uevent from kernel normally
- #[ignore]
#[test]
fn test_monitor_kernel() {
+ let device = Device::from_subsystem_sysname("net", "lo").unwrap();
+ if device.trigger(DeviceAction::Change).is_err() {
+ return;
+ }
+
let e = Events::new().unwrap();
let s: Rc<dyn Source> = Rc::new(Monitor {
device_monitor: DeviceMonitor::new(MonitorNetlinkGroup::Kernel, None),
@@ -275,7 +279,7 @@ mod tests {
e.set_enabled(s.clone(), EventState::On).unwrap();
spawn(|| {
- let device = Device::from_devname("/dev/sda").unwrap();
+ let device = Device::from_subsystem_sysname("net", "lo").unwrap();
device.set_sysattr_value("uevent", Some("change")).unwrap();
})
.join()
@@ -287,9 +291,13 @@ mod tests {
}
/// test whether device monitor can receive device message from userspace normally
- #[ignore]
#[test]
fn test_monitor_userspace() {
+ let device = Device::from_subsystem_sysname("net", "lo").unwrap();
+ if device.trigger(DeviceAction::Change).is_err() {
+ return;
+ }
+
let e = Events::new().unwrap();
let s: Rc<dyn Source> = Rc::new(Monitor {
device_monitor: DeviceMonitor::new(MonitorNetlinkGroup::Userspace, None),
@@ -298,9 +306,8 @@ mod tests {
e.set_enabled(s.clone(), EventState::On).unwrap();
spawn(|| {
- let device = Device::from_devname("/dev/sda").unwrap();
+ let device = Device::from_subsystem_sysname("net", "lo").unwrap();
device.set_action_from_string("change").unwrap();
- device.set_subsystem("block");
device.set_seqnum(1000);
let broadcaster = DeviceMonitor::new(MonitorNetlinkGroup::None, None);
--
2.33.0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,410 @@
From 2d38b2906a0b71c1ea591d83fba9879ce9fb6e65 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Fri, 17 Nov 2023 06:01:41 +0800
Subject: [PATCH 072/103] test(devmaster): add UT cases for rules load
---
exts/devmaster/src/lib/rules/rules_load.rs | 342 +++++++++++++++++----
1 file changed, 287 insertions(+), 55 deletions(-)
diff --git a/exts/devmaster/src/lib/rules/rules_load.rs b/exts/devmaster/src/lib/rules/rules_load.rs
index 57ff19ac..e9dd2259 100644
--- a/exts/devmaster/src/lib/rules/rules_load.rs
+++ b/exts/devmaster/src/lib/rules/rules_load.rs
@@ -1725,7 +1725,6 @@ impl RuleToken {
#[cfg(test)]
mod tests {
- use crate::config::*;
use basic::fs_util::touch_file;
use log::init_log;
use log::Level;
@@ -1733,32 +1732,245 @@ mod tests {
use super::*;
use std::fs::create_dir_all;
use std::fs::remove_dir_all;
- use std::{fs, path::Path, thread::JoinHandle};
-
- fn create_test_rules_dir(dir: &'static str) {
- assert!(fs::create_dir(dir).is_ok());
- assert!(fs::write(
- format!("{}/test.rules", dir),
- "ACTION == \"change\", SYMLINK += \"test1\"
-ACTION == \"change\", SYMLINK += \"test11\", \\
-SYMLINK += \"test111\"
-ACTION == \"change\", SYMLINK += \"test1111\", \\
-SYMLINK += \"test11111\", \\
-SYMLINK += \"test111111\"",
- )
- .is_ok());
+ use std::io::Write;
+ use std::panic::catch_unwind;
+ use std::{fs, path::Path};
+
+ fn create_tmp_rules(dir: &'static str, file: &str, content: &str) {
+ assert!(fs::create_dir_all(dir).is_ok());
+ assert!(fs::write(format!("{}/{}", dir, file), content,).is_ok());
}
- fn clear_test_rules_dir(dir: &'static str) {
+ fn clear_tmp_rules(dir: &'static str) {
if Path::new(dir).exists() {
assert!(fs::remove_dir_all(dir).is_ok());
}
}
#[test]
- fn test_rules_new() {
+ fn test_load_rules() {
+ init_log(
+ "test_load_rules",
+ Level::Debug,
+ vec!["console"],
+ "",
+ 0,
+ 0,
+ false,
+ );
+ clear_tmp_rules("/tmp/devmaster/rules");
+
+ let legal_rule = vec![
+ "ACTION == \"change\", SYMLINK += \"test1\"", // Test legal rules.
+ "ACTION == \"change\", SYMLINK += \"test11\", \\
+ SYMLINK += \"test111\"", // Test double line tying.
+ "ACTION == \"change\", SYMLINK += \"test1111\", \\
+ SYMLINK += \"test11111\", \\
+ SYMLINK += \"test111111\"", // Test triple line tying.
+ "SYMLINK == \"$hello\"", // Illegal placeholder will throw warning rather than panic.
+ "NAME += \"xxx\"", // NAME will transfer operator += to =.
+ "NAME == \"$hello\"", // Illegal placeholder will throw warning rather than panic.
+ "ENV{xxx}:=\"xxx\"", // ENV will transfer final assignment := to =.
+ "ENV{xxx}=\"$hello\"", // Illegal placeholder will throw warning rather than panic.
+ "CONST{arch}==\"x86_64\"", // Test legal CONST usage.
+ "CONST{virt}==\"qemu\"", // Test legal CONST usage.
+ "SUBSYSTEM==\"bus\"", // SUBSYSTEM will throw warning if the value is 'bus' or 'class'.
+ "DRIVER==\"xxx\"", // Test DRIVER usage.
+ /* ATTR will throw warning if the operator is += or :=,
+ * and transfer the operator into =.
+ */
+ "ATTR{xxx}+=\"xxx\"",
+ "ATTR{xxx}:=\"xxx\"",
+ "ATTR{xxx}=\"$hello\"", // Illegal placeholder in value will throw warning rather than panic.
+ /* Test SYSCTL usage. */
+ "SYSCTL{hello}=\"world\"",
+ "SYSCTL{hello}==\"world\"",
+ /* SYSCTL will transfer the += and := operator to =, and trow warning. */
+ "SYSCTL{hello}+=\"world\"",
+ "SYSCTL{hello}:=\"world\"",
+ "SYSCTL{hello}=\"$hello\"", // Illegal placeholder in value will throw warning rather than panic.
+ "ATTRS{device/xxx}==\"xxx\"", // The attribute with prefix of 'device/' will trow warning.
+ "ATTRS{../xxx}==\"xxx\"", // The attribute with prefix of 'device/' will throw warning.
+ "TAGS==\"xxx\"", // Test TAGS usage.
+ "TEST{777}==\"xx\"", // Test TEST usage.
+ "TEST{777}==\"$hello\"", // Illegal placeholder in value will throw warning rather than panic.
+ "PROGRAM==\"$hello\"", // Illegal placeholder in value will throw warning rather than panic.
+ "IMPORT{program}==\"$hello\"", // Illegal placeholder in value will throw warning rather than panic.
+ "IMPORT{file}=\"x\"", // IMPORT will throw warning if the operator is not matching or unmatching and transfer it to ==.
+ "IMPORT{program}==\"path_id $kernel\"", // If the program is a built-in command, IMPORT will identify it.
+ /* Test OPTIONS usages. */
+ "OPTIONS+=\"string_escape=none\"",
+ "OPTIONS+=\"db_persist\"",
+ "OPTIONS+=\"log_level=rest\"",
+ "OPTIONS+=\"log_level=10\"",
+ "OWNER+=\"0\"", // OWNER will transfer += to =, and trow a warning.
+ "GROUP+=\"0\"", // GROUP will transfer += to =, and trow a warning.
+ "MODE+=\"777\"", // MODE will transfer += to =, and trow a warning.
+ "MODE=\"$hello\"", // Illegal placeholder in value will throw warning rather than panic.
+ "SECLABEL{x}:=\"$hello\"", // Illegal placeholder in value will throw warning rather than panic.
+ ];
+
+ create_tmp_rules("/tmp/devmaster/rules", "00-test.rules", "");
+
+ for &content in legal_rule.iter() {
+ let mut f = fs::OpenOptions::new()
+ .write(true)
+ .truncate(true)
+ .open("/tmp/devmaster/rules/00-test.rules")
+ .unwrap();
+ f.write_all(content.as_bytes()).unwrap();
+
+ let _ = Rules::load_rules(
+ vec!["/tmp/devmaster/rules".to_string()],
+ ResolveNameTime::Early,
+ );
+ }
+
+ clear_tmp_rules("/tmp/devmaster/rules");
+ }
+
+ #[test]
+ fn test_load_rules_panic() {
+ init_log(
+ "test_load_rules_panic",
+ Level::Debug,
+ vec!["console"],
+ "",
+ 0,
+ 0,
+ false,
+ );
+ clear_tmp_rules("/tmp/devmaster/rules");
+
+ let illegal_rule = vec![
+ "action==\"change\"", // Error in State::Pre
+ "ACtion==\"change\"", // Error in State::Key
+ "ENV{!}==\"hello\"", // Error in State::Attribute
+ "ACTION #= \"hello\"", // Error in State::PreOp
+ "ACTION =# \"hello\"", // Error in State::Op
+ "ACTION == hello", // Error in State::PostOp
+ "ACTION == \"change\"x", // Error in State::PostValue
+ "ACTION = \"change\"", // ACTION can not take assign operator.
+ "DEVPATH{xxx} == \"xxx\"", // DEVPATH can not take attribute.
+ "DEVPATH = \"xxx\"", // DEVPATH can no take assign operator.
+ "KERNEL{xxx} == \"xxx\"", // KERNEL can not take attribute.
+ "KERNEL = \"xxx\"", // KERNEL can not take assign operator.
+ "SYMLINK{xxx} = \"hello\"", // SYMLINK can not take attribute.
+ "NAME{xxx} = \"xxx\"", // NAME can not take attribute.
+ "NAME -= \"xxx\"", // NAME can not take removal operator.
+ "NAME=\"%k\"", // NAME can not take '%k' value.
+ "NAME=\"\"", // NAME can not take empty value.
+ "ENV=\"xxx\"", // ENV must take attribute.
+ "ENV{xxx}-=\"xxx\"", // ENV can not take removal operator.
+ /* ENV with non-match operator can not take the following attributes:
+ * "ACTION"
+ * "DEVLINKS"
+ * "DEVNAME"
+ * "DEVTYPE"
+ * "DRIVER"
+ * "IFINDEX"
+ * "MAJOR"
+ * "MINOR"
+ * "SEQNUM"
+ * "SUBSYSTEM"
+ * "TAGS"
+ */
+ "ENV{ACTION}=\"xxx\"",
+ "ENV{DEVLINKS}=\"xxx\"",
+ "ENV{DEVNAME}=\"xxx\"",
+ "ENV{DEVTYPE}=\"xxx\"",
+ "ENV{DRIVER}=\"xxx\"",
+ "ENV{IFINDEX}=\"xxx\"",
+ "ENV{MAJOR}=\"xxx\"",
+ "ENV{MINOR}=\"xxx\"",
+ "ENV{SEQNUM}=\"xxx\"",
+ "ENV{SUBSYSTEM}=\"xxx\"",
+ "ENV{TAGS}=\"xxx\"",
+ "CONST==\"xxx\"", // CONST must take an attribute.
+ "CONST{xxx}==\"xxx\"", // CONST can only take "arch" or "virt" attribute.
+ "CONST{virt}=\"qemu\"", // CONST can not take assignment operator.
+ "TAG{xxx}+=\"xxx\"", // TAG can not take attribute.
+ "SUBSYSTEM{xxx}==\"block\"", // SUBSYSTEM can not take attribute.
+ "SUBSYSTEM=\"block\"", // SUBSYSTEM can only take matching or unmatching operators.
+ "DRIVER{xxx}==\"xxx\"", // DRIVER can not take attribute.
+ "DRIVER=\"xxx\"", // DRIVER can only take matching or unmatching operators.
+ "ATTR{$hello}==\"xxx\"", // ATTR can not take illegal attribute.
+ "ATTR{hello}-=\"xxx\"", // ATTR can not take removal operator.
+ /* SYSCTL must take attribute. */
+ "SYSCTL=\"xxx\"",
+ "SYSCTL==\"xxx\"",
+ "SYSCTL{xxx}-=\"xxx\"", // SYSCTL can not take removal operator.
+ "KERNELS{xxx}==\"xxx\"", // KERNELS can not take attribute.
+ "KERNELS=\"xxx\"", // KERNELS can only take matching or unmatching operators.
+ "SUBSYSTEMS{xxx}==\"xxx\"", // SUBSYSTEMS can not take attribute.
+ "SUBSYSTEMS=\"xxx\"", // SUBSYSTEMS can not take assignment operators.
+ "DRIVERS{xxx}=\"xxx\"", // DRIVERS can not take attribute.
+ "DRIVERS=\"xxx\"", // DRIVERS can not take assignment operators.
+ "ATTRS==\"xxx\"", // ATTRS must take an attribute.
+ "ATTRS{xxx}=\"x\"", // ATTRS can not take assignment operators.
+ "TAGS{xxx}=\"xxx\"", // TAGS can not take attribute.
+ "TAGS=\"xxx\"", // TAGS can not take assignment operators.
+ "TEST{777}=\"x\"", // TEST can not take assignment operators.
+ "PROGRAM{x}==\"x\"", // PROGRAM can not take attribute.
+ "PROGRAM-=\"x\"", // PROGRAM can not take removal attribute.
+ "IMPORT==\"x\"", // IMPORT must take an attribute.
+ "IMPORT{builtin}==\"xxx $kernel\"", // IMPORT{builtin} will panic if the command is not a valid built-in.
+ "IMPORT{x}==\"x\"", // IMPORT will panic if the attribute is invalid.
+ "RESULT{x}==\"x\"", // RESULT can not take attribute.
+ "RESULT{x}=\"x\"", // RESULT can only take matching or unmatching operator.
+ "OPTIONS{x}+=\"x\"", // OPTIONS can not take attribute.
+ "OPTIONS{x}==\"x\"", // OPTIONS can not take matching or unmatching operator.
+ "OPTIONS{x}-=\"x\"", // OPTIONS can not take removal operator.
+ "OPTIONS+=\"link_priority=x\"", // Invalid number of link priority.
+ "OPTIONS+=\"log_level=xxx\"", // Invalid log_level.
+ "OWNER{x}==\"x\"", // OWNER can not take attribute.
+ "OWNER==\"0\"", // OWNER can not take matching or unmatching operator.
+ "OWNER-=\"0\"", // OWNER can not take removal operator.
+ "GROUP==\"0\"", // OWNER can not take matching or unmatching operator.
+ "GROUP-=\"0\"", // OWNER can not take removal operator.
+ "MODE{x}=\"777\"", // MODE can not take attribute.
+ "MODE==\"777\"", // MODE can not take matching or unmatching operator.
+ "MODE-=\"777\"", // MODE can not take removal operator.
+ "SECLABEL=\"xxx\"", // SECLABEL must take an attribute.
+ "SECLABEL{x}==\"x\"", // SECLABEL can not take matching or unmatching operator.
+ "SECLABEL{x}-=\"x\"", // SECLABEL can not take removal operator.
+ "RUN==\"xxx\"", // RUN can not take matching or unmatching operator.
+ "RUN-=\"xxx\"", // RUN can not take removal operator.
+ "RUN{builtin}==\"xxx\"", // RUN will panic if the builtin is invalid.
+ "RUN{xxx}==\"xxx\"", // RUN will panic if the attribute is not builtin or program.
+ "GOTO{xx}=\"xx\"", // GOTO can not take attribute.
+ "GOTO==\"xx\"", // GOTO can only take assignment operator.
+ "LABEL{x}==\"x\"", // LABEL can not take attribute.
+ "LABEL==\"x\"", // LABEL can only take assignment operator.
+ "XXX=\"xxx\"", // Invalid token key.
+ ];
+
+ create_tmp_rules("/tmp/devmaster/rules", "00-test.rules", "");
+
+ for content in illegal_rule.iter() {
+ let mut f = fs::OpenOptions::new()
+ .write(true)
+ .truncate(true)
+ .open("/tmp/devmaster/rules/00-test.rules")
+ .unwrap();
+ f.write_all(content.as_bytes()).unwrap();
+
+ assert!(catch_unwind(|| {
+ let _ = Rules::load_rules(
+ vec!["/tmp/devmaster/rules".to_string()],
+ ResolveNameTime::Early,
+ );
+ })
+ .is_err());
+ }
+
+ clear_tmp_rules("/tmp/devmaster/rules");
+ }
+
+ #[test]
+ fn test_resolve_name_time() {
init_log(
- "test_rules_new",
+ "test_load_rules",
Level::Debug,
vec!["console"],
"",
@@ -1766,11 +1978,50 @@ SYMLINK += \"test111111\"",
0,
false,
);
- clear_test_rules_dir("test_rules_new");
- create_test_rules_dir("test_rules_new");
- let rules = Rules::load_rules(DEFAULT_RULES_DIRS.to_vec(), ResolveNameTime::Early);
- println!("{}", rules.read().unwrap());
- clear_test_rules_dir("test_rules_new");
+ clear_tmp_rules("/tmp/devmaster/rules");
+
+ let legal = vec!["OWNER=\"root\"", "GROUP=\"root\""];
+ let illegal = vec!["OWNER=\"xxxx\"", "GROUP=\"xxxx\""];
+
+ create_tmp_rules("/tmp/devmaster/rules", "00-test.rules", "");
+
+ for &content in legal.iter() {
+ let mut f = fs::OpenOptions::new()
+ .write(true)
+ .truncate(true)
+ .open("/tmp/devmaster/rules/00-test.rules")
+ .unwrap();
+ f.write_all(content.as_bytes()).unwrap();
+
+ let _ = Rules::load_rules(
+ vec!["/tmp/devmaster/rules".to_string()],
+ ResolveNameTime::Early,
+ );
+ }
+
+ for &content in illegal.iter() {
+ let mut f = fs::OpenOptions::new()
+ .write(true)
+ .truncate(true)
+ .open("/tmp/devmaster/rules/00-test.rules")
+ .unwrap();
+ f.write_all(content.as_bytes()).unwrap();
+
+ let _ = Rules::load_rules(
+ vec!["/tmp/devmaster/rules".to_string()],
+ ResolveNameTime::Late,
+ );
+
+ assert!(catch_unwind(|| {
+ let _ = Rules::load_rules(
+ vec!["/tmp/devmaster/rules".to_string()],
+ ResolveNameTime::Early,
+ );
+ })
+ .is_err());
+ }
+
+ clear_tmp_rules("/tmp/devmaster/rules");
}
#[test]
@@ -1955,34 +2206,6 @@ SYMLINK += \"test111111\"",
println!("{:?}", t);
}
- #[test]
- fn test_rules_share_among_threads() {
- create_test_rules_dir("test_rules_share_among_threads");
- let rules = Rules::new(
- vec![
- "test_rules_new_1".to_string(),
- "test_rules_new_2".to_string(),
- ],
- ResolveNameTime::Early,
- );
- let mut handles = Vec::<JoinHandle<()>>::new();
- (0..5).for_each(|i| {
- let rules_clone = rules.clone();
- let handle = std::thread::spawn(move || {
- println!("thread {}", i);
- println!("{}", rules_clone);
- });
-
- handles.push(handle);
- });
-
- for thread in handles {
- thread.join().unwrap();
- }
-
- clear_test_rules_dir("test_rules_share_among_threads");
- }
-
#[test]
fn test_resolve_user_group() {
let mut rules = Rules::new(vec![], ResolveNameTime::Early);
@@ -2124,18 +2347,27 @@ SYMLINK += \"test111111\"",
touch_file(
"/tmp/devmaster/rules/02-c.rules",
false,
- Some(0o222),
+ Some(0o000),
None,
None,
)
.unwrap();
- let rules = Rules::new(
+ let rules = Arc::new(RwLock::new(Rules::new(
vec!["/tmp/devmaster/rules".to_string()],
ResolveNameTime::Never,
- );
+ )));
+
+ // Rules::parse_rules(Arc::new(RwLock::new(rules)));
- Rules::parse_rules(Arc::new(RwLock::new(rules)));
+ RuleFile::load_file("/tmp/devmaster/rules/00-a.rules".to_string(), rules.clone());
+
+ if nix::unistd::getuid().as_raw() != 0 {
+ assert!(catch_unwind(|| {
+ RuleFile::load_file("/tmp/devmaster/rules/02-c.rules".to_string(), rules.clone());
+ })
+ .is_err());
+ }
remove_dir_all("/tmp/devmaster").unwrap();
}
--
2.33.0

View File

@ -0,0 +1,275 @@
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

View File

@ -0,0 +1,134 @@
From e0d987db5fb3a13b07e148991af3aa8c434cb074 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Fri, 24 Nov 2023 15:09:11 +0800
Subject: [PATCH 086/103] test(devmaster): add UT for node and modify the
displaying format of rules token
---
exts/devmaster/src/lib/rules/node.rs | 103 ++++++++++++++++++++++++++-
1 file changed, 101 insertions(+), 2 deletions(-)
diff --git a/exts/devmaster/src/lib/rules/node.rs b/exts/devmaster/src/lib/rules/node.rs
index 9fba906e..de600f72 100644
--- a/exts/devmaster/src/lib/rules/node.rs
+++ b/exts/devmaster/src/lib/rules/node.rs
@@ -702,10 +702,11 @@ pub(crate) fn cleanup_prior_dir() -> Result<()> {
#[cfg(test)]
mod test {
use super::*;
- use basic::fs_util::is_symlink;
+ use basic::fs_util::{is_symlink, touch_file};
+ use device::device_enumerator::*;
use device::utils::LoopDev;
use nix::unistd::unlink;
- use std::fs::{self, read_link, remove_dir, remove_dir_all};
+ use std::fs::{self, read_link, remove_dir, remove_dir_all, remove_file};
#[test]
fn test_update_node() {
@@ -816,4 +817,102 @@ mod test {
}
}
}
+
+ #[test]
+ fn test_escape_prior_dir() {
+ assert_eq!(&escape_prior_dir("aaa/bbb"), "aaa\\x2fbbb");
+ assert_eq!(&escape_prior_dir("aaa\\bbb"), "aaa\\x5cbbb");
+ }
+
+ #[test]
+ fn test_get_prior_dir() {
+ assert_eq!(
+ get_prior_dir("/../xxx").unwrap_err().get_errno(),
+ nix::Error::EINVAL
+ );
+ assert_eq!(
+ get_prior_dir("xxx").unwrap_err().get_errno(),
+ nix::Error::EINVAL
+ );
+ }
+
+ #[test]
+ fn test_prior_dir_read_one() {
+ if let Err(e) =
+ LoopDev::inner_process("/tmp/test_prior_dir_read_one", 1024 * 1024 * 10, |dev| {
+ let devname = dev.get_devname().unwrap();
+ let id = dev.get_device_id().unwrap();
+
+ create_dir_all("/tmp/test_prior_dir_read_one_dir").unwrap();
+
+ let p = Path::new("/tmp/test_prior_dir_read_one_dir");
+
+ let dir = nix::dir::Dir::open(p, OFlag::O_DIRECTORY, Mode::S_IRWXU).unwrap();
+
+ /* Missing link priority. */
+ symlink(
+ &format!(":{}", devname),
+ &format!("/tmp/test_prior_dir_read_one_dir/{}", id),
+ false,
+ )
+ .unwrap();
+
+ prior_dir_read_one(dir.as_raw_fd(), &id).unwrap_err();
+
+ /* Non-existing device node path. */
+ symlink(
+ "0:xxx",
+ &format!("/tmp/test_prior_dir_read_one_dir/{}", id),
+ false,
+ )
+ .unwrap();
+
+ prior_dir_read_one(dir.as_raw_fd(), &id).unwrap_err();
+
+ remove_dir_all("/tmp/test_prior_dir_read_one_dir").unwrap();
+
+ Ok(())
+ })
+ {
+ assert!(e.is_errno(nix::Error::EACCES) || e.is_errno(nix::Error::EBUSY));
+ }
+ }
+
+ #[test]
+ fn test_node_symlink() {
+ if let Err(e) = LoopDev::inner_process("/tmp/test_node_symlink", 1024 * 1024 * 10, |dev| {
+ let dev = Rc::new(RefCell::new(dev.shallow_clone().unwrap()));
+
+ touch_file(
+ "/tmp/test_node_symlink_link",
+ false,
+ Some(0o777),
+ None,
+ None,
+ )
+ .unwrap();
+
+ /* If the target exists, the symlink will not be created. */
+ node_symlink(dev, "", "/tmp/test_node_symlink_link").unwrap_err();
+
+ remove_file("/tmp/test_node_symlink_link").unwrap();
+
+ Ok(())
+ }) {
+ assert!(e.is_errno(nix::Error::EACCES) || e.is_errno(nix::Error::EBUSY));
+ }
+ }
+
+ #[test]
+ fn test_device_get_symlink_by_devnum() {
+ let mut e = DeviceEnumerator::new();
+ e.set_enumerator_type(DeviceEnumerationType::Devices);
+ e.add_match_subsystem("tty", true).unwrap();
+ e.add_match_subsystem("block", true).unwrap();
+
+ for d in e.iter() {
+ let s = device_get_symlink_by_devnum(d).unwrap();
+ println!("{}", s);
+ }
+ }
}
--
2.33.0

View File

@ -0,0 +1,947 @@
From 9eab33e9cfaa97cac808ba5ebc3c2d2c30157681 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Wed, 22 Nov 2023 15:45:16 +0800
Subject: [PATCH 079/103] test(devmaster): add UT for rules applying
---
exts/devmaster/src/lib/rules/exec_mgr.rs | 917 +++++++++++++++++++++++
1 file changed, 917 insertions(+)
diff --git a/exts/devmaster/src/lib/rules/exec_mgr.rs b/exts/devmaster/src/lib/rules/exec_mgr.rs
index 66c1a06c..03da901d 100644
--- a/exts/devmaster/src/lib/rules/exec_mgr.rs
+++ b/exts/devmaster/src/lib/rules/exec_mgr.rs
@@ -2140,8 +2140,13 @@ impl RuleLine {
#[cfg(test)]
mod tests {
+ use std::fs::remove_file;
+
use super::*;
+ use crate::rules::rules_load::tests::create_tmp_file;
use crate::rules::FormatSubstitutionType;
+ use device::utils::LoopDev;
+ use log::{init_log, Level};
#[test]
#[ignore]
@@ -2294,4 +2299,916 @@ mod tests {
assert_eq!(unit.apply_format("$parent", false).unwrap(), "sda");
assert_eq!(unit.apply_format("$devnode", false).unwrap(), "/dev/sda1");
}
+
+ impl ExecuteManager {
+ #[allow(clippy::too_many_arguments)]
+ fn test_apply_one_rule_token(
+ &self,
+ key: &str,
+ attr: &str,
+ op: &str,
+ value: &str,
+ rules: Arc<RwLock<Rules>>,
+ rule_line: Arc<RwLock<Option<RuleLine>>>,
+ device: Rc<RefCell<Device>>,
+ ) -> Result<bool> {
+ let token = RuleToken::parse_token(
+ key.to_string(),
+ if attr.is_empty() {
+ None
+ } else {
+ Some(attr.to_string())
+ },
+ op.to_string(),
+ value.to_string(),
+ rules,
+ rule_line,
+ )
+ .unwrap();
+ *self.current_rule_token.borrow_mut() = Arc::new(RwLock::new(Some(token)));
+ self.apply_rule_token(device)
+ }
+ }
+
+ #[test]
+ fn test_apply_rules() {
+ init_log(
+ "test_apply_rules",
+ Level::Debug,
+ vec!["console"],
+ "",
+ 0,
+ 0,
+ false,
+ );
+
+ let device = Rc::new(RefCell::new(
+ Device::from_subsystem_sysname("net", "lo").unwrap(),
+ ));
+ device.borrow().set_base_path("/tmp/devmaster");
+ let rules = Arc::new(RwLock::new(Rules::new(vec![], ResolveNameTime::Early)));
+ let rule_file = Arc::new(RwLock::new(Some(RuleFile::new("".to_string()))));
+ let rule_line = Arc::new(RwLock::new(Some(RuleLine::new(
+ "".to_string(),
+ 0,
+ rule_file,
+ ))));
+ let unit = ExecuteUnit::new(device.clone());
+ let mgr = ExecuteManager::new(Arc::new(RwLock::new(Cache::new(vec![], vec![]))));
+ *mgr.current_unit.borrow_mut() = Some(unit);
+
+ device.borrow().set_action_from_string("change").unwrap();
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "ACTION",
+ "",
+ "==",
+ "change",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ assert!(!mgr
+ .test_apply_one_rule_token(
+ "ACTION",
+ "",
+ "==",
+ "add",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "DEVPATH",
+ "",
+ "==",
+ "*lo",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(!mgr
+ .test_apply_one_rule_token(
+ "ENV",
+ "xxx",
+ "==",
+ "xxx",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ device.borrow().add_tag("xxx", true);
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "TAG",
+ "",
+ "==",
+ "xxx",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "SUBSYSTEM",
+ "",
+ "==",
+ "net",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "TEST",
+ "444",
+ "==",
+ "[net/lo]ifindex",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "TEST",
+ "644",
+ "==",
+ "queues/*/rps_cpus",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "TEST",
+ "444",
+ "==",
+ "ifindex",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "TEST",
+ "",
+ "!=",
+ "asfsdfa",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(!mgr
+ .test_apply_one_rule_token(
+ "TEST",
+ "444",
+ "==",
+ "$attr",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ create_tmp_file(
+ "/tmp",
+ "property",
+ "HELLO=WORLD
+GOOD=LUCK",
+ true,
+ );
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "IMPORT",
+ "file",
+ "==",
+ "/tmp/property",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert_eq!(
+ &device.borrow().get_property_value("HELLO").unwrap(),
+ "WORLD"
+ );
+
+ assert_eq!(&device.borrow().get_property_value("GOOD").unwrap(), "LUCK");
+
+ remove_file("/tmp/property").unwrap();
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "IMPORT",
+ "program",
+ "==",
+ "echo WATER=FLOW",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ assert_eq!(
+ &device.borrow().get_property_value("WATER").unwrap(),
+ "FLOW"
+ );
+
+ create_tmp_file(
+ "/tmp/devmaster/data",
+ &device.borrow().get_device_id().unwrap(),
+ "E:BLACK=PINK",
+ true,
+ );
+ mgr.current_unit
+ .borrow()
+ .as_ref()
+ .unwrap()
+ .clone_device_db()
+ .unwrap();
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "IMPORT",
+ "db",
+ "==",
+ "BLACK",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ assert_eq!(
+ &device.borrow().get_property_value("BLACK").unwrap(),
+ "PINK"
+ );
+ remove_file(&format!(
+ "/tmp/devmaster/data/{}",
+ device.borrow().get_device_id().unwrap()
+ ))
+ .unwrap();
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "IMPORT",
+ "cmdline",
+ "==",
+ "root",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ assert!(!device
+ .borrow()
+ .get_property_value("root")
+ .unwrap()
+ .is_empty());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "IMPORT",
+ "cmdline",
+ "!=",
+ "asdfasdf",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(!mgr
+ .test_apply_one_rule_token(
+ "PROGRAM",
+ "",
+ "==",
+ "echo $attr",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(!mgr
+ .test_apply_one_rule_token(
+ "PROGRAM",
+ "",
+ "==",
+ "cat /tmp/test_nonexist",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(!mgr
+ .test_apply_one_rule_token(
+ "PROGRAM",
+ "",
+ "==",
+ "asdfasdf",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "PROGRAM",
+ "",
+ "==",
+ "echo hello",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "RESULT",
+ "",
+ "==",
+ "hello",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "OPTIONS",
+ "",
+ "+=",
+ "string_escape=none",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "OPTIONS",
+ "",
+ "+=",
+ "string_escape=replace",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "OPTIONS",
+ "",
+ "+=",
+ "db_persist",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "OPTIONS",
+ "",
+ "+=",
+ "db_persist",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "OPTIONS",
+ "",
+ "+=",
+ "link_priority=1",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "OWNER",
+ "",
+ "=",
+ "0",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "GROUP",
+ "",
+ "=",
+ "0",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "MODE",
+ "",
+ "=",
+ "777",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ rules.write().unwrap().resolve_name_time = ResolveNameTime::Late;
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "OWNER",
+ "",
+ "=",
+ "root",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "GROUP",
+ "",
+ "=",
+ "root",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ mgr.test_apply_one_rule_token(
+ "ENV",
+ "mode",
+ "=",
+ "777",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap();
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "MODE",
+ "",
+ "=",
+ "$env{mode}",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ rules.write().unwrap().resolve_name_time = ResolveNameTime::Early;
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "OWNER",
+ "",
+ ":=",
+ "0",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "GROUP",
+ "",
+ ":=",
+ "0",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "MODE",
+ "",
+ ":=",
+ "777",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "OWNER",
+ "",
+ "=",
+ "0",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "GROUP",
+ "",
+ "=",
+ "0",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "MODE",
+ "",
+ "=",
+ "777",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "ENV",
+ "BLACK",
+ "=",
+ "YELLOW",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ assert_eq!(
+ &device.borrow().get_property_value("BLACK").unwrap(),
+ "YELLOW"
+ );
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "TAG",
+ "",
+ "+=",
+ "aaa",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ assert!(device.borrow().has_tag("aaa").unwrap());
+ assert!(device.borrow().has_current_tag("aaa").unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "TAG",
+ "",
+ "-=",
+ "aaa",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ assert!(device.borrow().has_tag("aaa").unwrap());
+ assert!(!device.borrow().has_current_tag("aaa").unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "TAG",
+ "",
+ "=",
+ "bbb",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ assert!(!device.borrow().has_tag("aaa").unwrap());
+ assert!(!device.borrow().has_current_tag("aaa").unwrap());
+ assert!(device.borrow().has_tag("bbb").unwrap());
+ assert!(device.borrow().has_current_tag("bbb").unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "NAME",
+ "",
+ ":=",
+ "test",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "NAME",
+ "",
+ "=",
+ "test",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ if mgr
+ .test_apply_one_rule_token(
+ "ATTR",
+ "ifalias",
+ "=",
+ "test",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .is_ok()
+ {
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "ATTR",
+ "ifalias",
+ "==",
+ "test",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ }
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "RUN",
+ "builtin",
+ "+=",
+ "path_id",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "ENV",
+ "PAPER",
+ "+=",
+ "",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "ENV",
+ "PAPER",
+ "==",
+ "",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "ENV",
+ "PAPER",
+ "=",
+ "",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "ENV",
+ "PAPER",
+ "==",
+ "",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "ENV",
+ "PAPER",
+ "+=",
+ "BOOK",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+ assert_eq!(
+ &device.borrow().get_property_value("PAPER").unwrap(),
+ "BOOK"
+ );
+
+ assert!(!mgr
+ .test_apply_one_rule_token(
+ "IMPORT",
+ "builtin",
+ "==",
+ "path_id $attr",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "TAG",
+ "",
+ "+=",
+ "$env",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "NAME",
+ "",
+ "=",
+ "$env",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "ATTR",
+ "ifalias",
+ "=",
+ "$env",
+ rules.clone(),
+ rule_line.clone(),
+ device.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "RUN",
+ "",
+ "+=",
+ "$env",
+ rules.clone(),
+ rule_line.clone(),
+ device,
+ )
+ .unwrap());
+
+ // /* TODO rules */
+ // let rules_c = rules.clone();
+ // let rule_line_c = rule_line.clone();
+ // let device_c = device.clone();
+ // assert!(catch_unwind(move || {
+ // let _ = mgr.test_apply_one_rule_token(
+ // "CONST",
+ // "virt",
+ // "==",
+ // "xxx",
+ // rules_c,
+ // rule_line_c,
+ // device_c,
+ // );
+ // })
+ // .is_err());
+
+ match LoopDev::new("/tmp/test_apply_rules", 1024 * 1024 * 10) {
+ Ok(lo) => {
+ let devpath = lo.get_device_path().unwrap();
+ let dev = Rc::new(RefCell::new(
+ Device::from_path(devpath.to_str().unwrap()).unwrap(),
+ ));
+ dev.borrow().set_base_path("/tmp/devmaster");
+
+ dev.borrow().add_devlink("/dev/test").unwrap();
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "SYMLINK",
+ "",
+ "==",
+ "/dev/test",
+ rules.clone(),
+ rule_line.clone(),
+ dev.clone(),
+ )
+ .unwrap());
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "SYMLINK",
+ "",
+ "!=",
+ "/dev/xxx",
+ rules.clone(),
+ rule_line.clone(),
+ dev.clone(),
+ )
+ .unwrap());
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "SYMLINK",
+ "",
+ "+=",
+ "xxx",
+ rules.clone(),
+ rule_line.clone(),
+ dev.clone(),
+ )
+ .unwrap());
+ assert!(dev.borrow().has_devlink("/dev/xxx"));
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "OPTIONS",
+ "",
+ "+=",
+ "watch",
+ rules.clone(),
+ rule_line.clone(),
+ dev.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token(
+ "OPTIONS",
+ "",
+ ":=",
+ "watch",
+ rules.clone(),
+ rule_line.clone(),
+ dev.clone(),
+ )
+ .unwrap());
+
+ assert!(mgr
+ .test_apply_one_rule_token("OPTIONS", "", "=", "watch", rules, rule_line, dev,)
+ .unwrap());
+ }
+ Err(e) => {
+ assert!(e.is_errno(nix::Error::EACCES) || e.is_errno(nix::Error::EBUSY));
+ }
+ }
+ }
}
--
2.33.0

View File

@ -0,0 +1,147 @@
From 124af0af5a9e28d70a362463a69a5daab3b70712 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Fri, 24 Nov 2023 15:08:07 +0800
Subject: [PATCH 085/103] test(devmaster): add UT for rules module
---
exts/devmaster/src/lib/rules/mod.rs | 105 ++++++++++++++++++++++++----
1 file changed, 90 insertions(+), 15 deletions(-)
diff --git a/exts/devmaster/src/lib/rules/mod.rs b/exts/devmaster/src/lib/rules/mod.rs
index a88a5f99..b5ee3c7d 100644
--- a/exts/devmaster/src/lib/rules/mod.rs
+++ b/exts/devmaster/src/lib/rules/mod.rs
@@ -218,9 +218,12 @@ impl RuleToken {
#[inline]
pub(crate) fn get_token_content(&self) -> String {
if let Some(attribute) = self.get_token_attribute() {
- format!("{}{{{}}}{}{}", self.r#type, attribute, self.op, self.value)
+ format!(
+ "{}{{{}}}{}\"{}\"",
+ self.r#type, attribute, self.op, self.value
+ )
} else {
- format!("{}{}{}", self.r#type, self.op, self.value)
+ format!("{}{}\"{}\"", self.r#type, self.op, self.value)
}
}
}
@@ -316,7 +319,7 @@ impl Display for TokenType {
Self::MatchParentsDriver => "DRIVERS",
Self::MatchParentsAttr => "ATTRS",
Self::MatchParentsTag => "TAGS",
- Self::MatchResult => "RESULTS",
+ Self::MatchResult => "RESULT",
Self::MatchTest => "TEST",
Self::MatchProgram => "PROGRAM",
Self::MatchImportFile
@@ -567,18 +570,6 @@ bitflags! {
}
}
-// bitflags! {
-// /// value matching type
-// pub(crate) struct MatchType: u8 {
-// /// match empty string
-// const EMPTY = 1<<0;
-// /// use shell glob parttern to match
-// const PATTERN = 1<<1;
-// /// match "subsystem", "bus", or "class"
-// const SUBSYSTEM = 1<<2;
-// }
-// }
-
/// match type
#[derive(Debug, Clone, Copy)]
#[allow(dead_code)]
@@ -744,3 +735,87 @@ pub(crate) enum EscapeType {
None,
Replace,
}
+
+#[cfg(test)]
+mod test {
+ use log::{init_log, Level};
+
+ use super::*;
+ use crate::rules::rules_load::tests::create_tmp_file;
+
+ #[test]
+ fn test_rules_display() {
+ init_log(
+ "test_rules_display",
+ Level::Debug,
+ vec!["console"],
+ "",
+ 0,
+ 0,
+ false,
+ );
+
+ create_tmp_file(
+ "/tmp/test_rules_display/rules.d",
+ "00-test.rules",
+ "
+ACTION==\"change\"
+DEVPATH==\"xxx\"
+KERNEL==\"xxx\"
+SYMLINK==\"xxx\"
+SYMLINK+=\"xxx\"
+NAME==\"xxx\"
+NAME=\"x\"
+ENV{x}=\"x\"
+ENV{x}==\"x\"
+CONST{virt}==\"x\"
+TAG+=\"x\"
+TAG==\"x\"
+SUBSYSTEM==\"x\"
+DRIVER==\"x\"
+ATTR{x}==\"x\"
+ATTR{x}=\"x\"
+SYSCTL{x}==\"x\"
+SYSCTL{x}=\"x\"
+KERNELS==\"x\"
+SUBSYSTEMS==\"x\"
+DRIVERS==\"x\"
+ATTRS{x}==\"x\"
+TAGS==\"x\"
+RESULT==\"x\"
+TEST==\"x\"
+PROGRAM==\"x\"
+IMPORT{file}==\"x\"
+IMPORT{program}==\"echo hello\"
+IMPORT{builtin}==\"path_id\"
+IMPORT{db}==\"x\"
+IMPORT{cmdline}==\"x\"
+IMPORT{parent}==\"x\"
+OPTIONS+=\"string_escape=none\"
+OPTIONS+=\"string_escape=replace\"
+OPTIONS+=\"db_persist\"
+OPTIONS+=\"watch\"
+OPTIONS+=\"link_priority=10\"
+OPTIONS+=\"log_level=1\"
+OPTIONS+=\"static_node=/dev/sda\"
+SECLABEL{x}+=\"x\"
+RUN{builtin}+=\"path_id\"
+RUN{program}+=\"x\"
+GOTO=\"x\"
+LABEL=\"x\"
+",
+ true,
+ );
+
+ let rule = Arc::new(RwLock::new(Rules::new(
+ vec!["/tmp/test_rules_display/rules.d".to_string()],
+ ResolveNameTime::Late,
+ )));
+
+ Rules::parse_rules(rule.clone());
+
+ println!("{}", rule.read().unwrap());
+
+ std::fs::remove_dir_all("/tmp/test_rules_display").unwrap();
+ }
+}
--
2.33.0

View File

@ -0,0 +1,167 @@
From 94a3a51db76f45f8941d8a6cb649da0624fde67b Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Thu, 16 Nov 2023 11:16:12 +0800
Subject: [PATCH 066/103] test(devmaster): optimize UT for testing framework
and add some new cases
---
exts/devmaster/src/bin/devctl/daemon/mod.rs | 7 ++
exts/devmaster/src/lib/framework/job_queue.rs | 85 ++++++++++++-------
.../src/lib/framework/worker_manager.rs | 1 +
3 files changed, 64 insertions(+), 29 deletions(-)
diff --git a/exts/devmaster/src/bin/devctl/daemon/mod.rs b/exts/devmaster/src/bin/devctl/daemon/mod.rs
index 3e4bd96d..53931650 100644
--- a/exts/devmaster/src/bin/devctl/daemon/mod.rs
+++ b/exts/devmaster/src/bin/devctl/daemon/mod.rs
@@ -71,6 +71,13 @@ mod test {
std::thread::sleep(std::time::Duration::from_secs(1));
let dev = Device::from_subsystem_sysname("net", "lo").unwrap();
+
+ /* Trigger more than the number of workers. */
+ dev.trigger(DeviceAction::Change).unwrap();
+ dev.trigger(DeviceAction::Change).unwrap();
+ dev.trigger(DeviceAction::Change).unwrap();
+ dev.trigger(DeviceAction::Change).unwrap();
+ dev.trigger(DeviceAction::Change).unwrap();
dev.trigger(DeviceAction::Change).unwrap();
/* Sleep more than 3 seconds to wait for the workers being recycled. */
diff --git a/exts/devmaster/src/lib/framework/job_queue.rs b/exts/devmaster/src/lib/framework/job_queue.rs
index 7c6d6a8d..e488f480 100644
--- a/exts/devmaster/src/lib/framework/job_queue.rs
+++ b/exts/devmaster/src/lib/framework/job_queue.rs
@@ -22,7 +22,6 @@ use std::{
cell::RefCell,
cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
collections::VecDeque,
- fmt::{self, Display},
rc::{Rc, Weak},
};
@@ -37,20 +36,8 @@ pub enum JobState {
Running,
}
-impl Display for JobState {
- ///
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let state = match self {
- JobState::Undef => "Undef",
- JobState::Queued => "Queued",
- JobState::Running => "Running",
- };
-
- write!(f, "{}", state)
- }
-}
-
/// device job
+#[derive(Debug)]
pub struct DeviceJob {
/// internal device
pub device: Device,
@@ -168,8 +155,6 @@ impl JobQueue {
gc.close_killer(e);
}
- // self.job_queue_show_state();
-
for job in self.jobs.borrow().iter() {
match job.get_state() {
JobState::Queued => {}
@@ -241,19 +226,6 @@ impl JobQueue {
log::debug!("Job Queue: insert job {}", seqnum);
}
- // /// cleanup the job queue, if match_state is Undef, cleanup all jobs, otherwise just retain the unmatched jobs
- // pub(crate) fn job_queue_cleanup(&self, match_state: JobState) {
- // self.jobs.borrow_mut().retain_mut(|job| {
- // if match_state != JobState::Undef && match_state != job.get_state() {
- // return true;
- // }
-
- // false
- // });
-
- // log::debug!("Job Queue: cleanup");
- // }
-
/// free a job from job queue
pub(crate) fn job_free(&self, job: &Rc<DeviceJob>) {
job.job_free();
@@ -289,3 +261,58 @@ impl JobQueue {
self.jobs.borrow().is_empty()
}
}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use std::sync::{Arc, RwLock};
+
+ #[test]
+ fn test_job_cmp() {
+ let j1 = DeviceJob::new(
+ Device::from_subsystem_sysname("net", "lo").unwrap(),
+ JobState::Queued,
+ 1000,
+ );
+
+ let j2 = DeviceJob::new(
+ Device::from_subsystem_sysname("net", "lo").unwrap(),
+ JobState::Queued,
+ 1000,
+ );
+
+ assert_eq!(j1, j2);
+ }
+
+ #[test]
+ fn test_job_queue() {
+ let events = Rc::new(Events::new().unwrap());
+ let cache = Cache::new(vec![], vec![]);
+ let devmaster = Rc::new(RefCell::new(Devmaster {
+ events,
+ worker_manager: None,
+ control_manager: None,
+ monitor: None,
+ job_queue: None,
+ gc: None,
+ cache: Arc::new(RwLock::new(cache)),
+ }));
+
+ let job_queue = JobQueue::new(devmaster);
+
+ /* Test start job when the queue is empty. */
+ job_queue.job_queue_start(None);
+
+ let dev = Device::from_subsystem_sysname("net", "lo").unwrap();
+ job_queue.job_queue_insert(dev);
+
+ /* Test insert dulplicate jobs with the same seqnum. */
+ let dev = Device::from_subsystem_sysname("net", "lo").unwrap();
+ dev.set_seqnum_from_string("1000").unwrap();
+ job_queue.job_queue_insert(dev);
+
+ let dev = Device::from_subsystem_sysname("net", "lo").unwrap();
+ dev.set_seqnum_from_string("1000").unwrap();
+ job_queue.job_queue_insert(dev);
+ }
+}
diff --git a/exts/devmaster/src/lib/framework/worker_manager.rs b/exts/devmaster/src/lib/framework/worker_manager.rs
index 870f6779..bddc9deb 100644
--- a/exts/devmaster/src/lib/framework/worker_manager.rs
+++ b/exts/devmaster/src/lib/framework/worker_manager.rs
@@ -64,6 +64,7 @@ pub struct WorkerManager {
}
/// worker
+#[derive(Debug)]
pub struct Worker {
/// worker unique id
id: u32,
--
2.33.0

View File

@ -0,0 +1,71 @@
From d661f601e4bb2b3ffcbb1db5bd11a51c6cf8abc1 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Fri, 17 Nov 2023 01:15:00 +0800
Subject: [PATCH 068/103] test(devmaster): test exception scenarios on parsing
rules
---
exts/devmaster/src/lib/rules/rules_load.rs | 38 ++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/exts/devmaster/src/lib/rules/rules_load.rs b/exts/devmaster/src/lib/rules/rules_load.rs
index cd90c271..19b7aaa4 100644
--- a/exts/devmaster/src/lib/rules/rules_load.rs
+++ b/exts/devmaster/src/lib/rules/rules_load.rs
@@ -1725,10 +1725,13 @@ impl RuleToken {
#[cfg(test)]
mod tests {
use crate::config::*;
+ use basic::fs_util::touch_file;
use log::init_log;
use log::Level;
use super::*;
+ use std::fs::create_dir_all;
+ use std::fs::remove_dir_all;
use std::{fs, path::Path, thread::JoinHandle};
fn create_test_rules_dir(dir: &'static str) {
@@ -2099,4 +2102,39 @@ SYMLINK += \"test111111\"",
);
assert_eq!(token.read().unwrap().as_ref().unwrap().value, "0");
}
+
+ #[test]
+ fn test_parse_rules() {
+ create_dir_all("/tmp/devmaster/rules").unwrap();
+
+ /* Normal rule file. */
+ touch_file(
+ "/tmp/devmaster/rules/00-a.rules",
+ false,
+ Some(0o777),
+ None,
+ None,
+ )
+ .unwrap();
+ /* Skip parsing the file with invalid suffix. */
+ touch_file("/tmp/devmaster/rules/01-b", false, Some(0o777), None, None).unwrap();
+ /* Failed to parse the file as it is not readable. */
+ touch_file(
+ "/tmp/devmaster/rules/02-c.rules",
+ false,
+ Some(0o222),
+ None,
+ None,
+ )
+ .unwrap();
+
+ let rules = Rules::new(
+ vec!["/tmp/devmaster/rules".to_string()],
+ ResolveNameTime::Never,
+ );
+
+ Rules::parse_rules(Arc::new(RwLock::new(rules)));
+
+ remove_dir_all("/tmp/devmaster").unwrap();
+ }
}
--
2.33.0

View File

@ -0,0 +1,45 @@
From e3056ffc97640c2791f73bc2aa24b0db07b9d60b Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Mon, 20 Nov 2023 14:47:22 +0800
Subject: [PATCH 074/103] test(devmaster): trigger add and remove uevent to
cover netif renaming procedure
The netif renaming procedure executes only when a add uevent of netif raised.
In addition, the remove process was not covered previously.
---
exts/devmaster/src/bin/devctl/daemon/mod.rs | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/exts/devmaster/src/bin/devctl/daemon/mod.rs b/exts/devmaster/src/bin/devctl/daemon/mod.rs
index 53931650..4aa957a4 100644
--- a/exts/devmaster/src/bin/devctl/daemon/mod.rs
+++ b/exts/devmaster/src/bin/devctl/daemon/mod.rs
@@ -61,7 +61,10 @@ mod test {
#[test]
fn test_run_daemon() {
- /* Require root privilege, skip in ci environment. */
+ /* Require root privilege, skip in ci environment.
+ *
+ * In addition, this test case will fail when devmaster daemon is running.
+ */
let dev = Device::from_subsystem_sysname("net", "lo").unwrap();
if dev.trigger(DeviceAction::Change).is_err() {
return;
@@ -73,9 +76,9 @@ mod test {
let dev = Device::from_subsystem_sysname("net", "lo").unwrap();
/* Trigger more than the number of workers. */
- dev.trigger(DeviceAction::Change).unwrap();
- dev.trigger(DeviceAction::Change).unwrap();
- dev.trigger(DeviceAction::Change).unwrap();
+ dev.trigger(DeviceAction::Remove).unwrap();
+ dev.trigger(DeviceAction::Add).unwrap();
+ dev.trigger(DeviceAction::Add).unwrap();
dev.trigger(DeviceAction::Change).unwrap();
dev.trigger(DeviceAction::Change).unwrap();
dev.trigger(DeviceAction::Change).unwrap();
--
2.33.0

View File

@ -0,0 +1,31 @@
From b018bb63d87f7c25acfbfc1964102fb1af64ce94 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Thu, 23 Nov 2023 20:14:43 +0800
Subject: [PATCH 083/103] test(devmaster): use unwrap instead of asserting is
ok
Use unwrap method to display more about error information.
---
exts/devmaster/src/lib/rules/rules_load.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/exts/devmaster/src/lib/rules/rules_load.rs b/exts/devmaster/src/lib/rules/rules_load.rs
index b035f562..49da2d63 100644
--- a/exts/devmaster/src/lib/rules/rules_load.rs
+++ b/exts/devmaster/src/lib/rules/rules_load.rs
@@ -1737,10 +1737,10 @@ pub(crate) mod tests {
use std::{fs, path::Path};
pub(crate) fn create_tmp_file(dir: &'static str, file: &str, content: &str, truncate: bool) {
- assert!(fs::create_dir_all(dir).is_ok());
+ fs::create_dir_all(dir).unwrap();
let s = format!("{}/{}", dir, file);
let p = Path::new(&s);
- assert!(fs::write(p, content,).is_ok());
+ fs::write(p, content).unwrap();
let mut f = fs::OpenOptions::new()
.write(true)
.truncate(truncate)
--
2.33.0

View File

@ -16,7 +16,7 @@
Name: sysmaster
Version: 0.5.1
Release: 3
Release: 4
Summary: redesign and reimplement process1.
License: Mulan PSL v2
@ -26,6 +26,49 @@ Source0: %{name}-%{version}.tar.xz
Patch0: backport-fix-getty-generator-delelte-double-quote-in-the-conf.patch
Patch1: backport-fix-solve-two-sysmaster-problem-exit-after-do_execut.patch
Patch2: backport-fix-solve-reboot-time-consuming.patch
Patch3: backport-feature-add-scsi_id.patch
Patch4: backport-feature-devctl-add-devctl-info.patch
Patch5: backport-fix-devmaster-keep-the-same-name-with-udev-control-s.patch
Patch6: backport-fix-devmaster-adjust-temporary-file-permissions.patch
Patch7: backport-fix-devmaster-append-zero-to-the-file-name.patch
Patch8: backport-fix-devmaster-fix-potential-integer-overflow-in-scsi.patch
Patch9: backport-fix-devmaster-fix-out-of-bounds-in-net_id.patch
Patch10: backport-fix-devmaster-fix-misspelt-sysattr-sas_address.patch
Patch11: backport-fix-devmaster-check-the-validity-of-kmod-context-dur.patch
Patch12: backport-feature-devmaster-Add-subcommands-for-devctl-trigger.patch
Patch13: backport-fix-return-Ok-when-the-.hwdb-and-hwdb.bin-files-cann.patch
Patch14: backport-fix-Failed-to-devctl-info-dev-or-sys.patch
Patch15: backport-fix-basic-complete-feature-dependencies.patch
Patch16: backport-fix-device-replenish-feature-dependency-of-uuid-on-b.patch
Patch17: backport-test-device-refactor-and-increase-test-line-coverage.patch
Patch18: backport-fix-basic-use-feature-to-control-procfs-compilation-.patch
Patch19: backport-test-device-compress-closures-and-add-some-unit-case.patch
Patch20: backport-fix-devmaster-drop-unnecessary-debug-trait-implement.patch
Patch21: backport-fix-device-fix-UT-privilege-error-in-ci.patch
Patch22: backport-fix-device-set-driver-subsystem-after-generating-dev.patch
Patch23: backport-fix-device-drop-unnecessary-error-throwing-out.patch
Patch24: backport-fix-device-cleanup-temporary-tag-files.patch
Patch25: backport-test-device-add-UT-for-device-enumerator.patch
Patch26: backport-test-device-add-UT-for-device-monitor.patch
Patch27: backport-feature-devmaster-add-devctl-control-subcommand-to-l.patch
Patch28: backport-refactor-devmaster-compress-unnecessary-code.patch
Patch29: backport-test-devmaster-optimize-UT-for-testing-framework-and.patch
Patch30: backport-test-devmaster-test-exception-scenarios-on-parsing-r.patch
Patch31: backport-fix-devmaster-cache-the-parsed-user-and-group.patch
Patch32: backport-fix-devmaster-drop-incorrect-preventation-on-removal.patch
Patch33: backport-fix-devmaster-CONST-can-only-take-arch-or-virt-as-at.patch
Patch34: backport-test-devmaster-add-UT-cases-for-rules-load.patch
Patch35: backport-test-devmaster-trigger-add-and-remove-uevent-to-cove.patch
Patch36: backport-fix-device-use-feature-to-avoid-loopdev-being-compil.patch
Patch37: backport-fix-devmaster-avoid-potential-test-case-failures.patch
Patch38: backport-refactor-devmaster-rename-the-create_tmp_rules-funct.patch
Patch39: backport-fix-device-keep-consistent-on-the-base-path-for-db-c.patch
Patch40: backport-test-devmaster-add-UT-for-rules-applying.patch
Patch41: backport-fix-device-avoid-panic-on-shallow-clone-when-subsyst.patch
Patch42: backport-test-devmaster-use-unwrap-instead-of-asserting-is-ok.patch
Patch43: backport-test-devmaster-add-UT-for-execute-unit.patch
Patch44: backport-test-devmaster-add-UT-for-rules-module.patch
Patch45: backport-test-devmaster-add-UT-for-node-and-modify-the-displa.patch
ExclusiveArch: x86_64 aarch64
@ -181,8 +224,11 @@ test -f /usr/lib/sysmaster/system/udevd.service && ln -s /usr/lib/sysmaster/syst
test -f /usr/lib/sysmaster/system/udev-trigger.service && ln -s /usr/lib/sysmaster/system/udev-trigger.service /etc/sysmaster/system/sysinit.target.wants/udev-trigger.service
%changelog
* Wed Dec 6 2023 chenjiayi<chenjiayi22@huawei.com> - 0.5.1-4
- sync patches from upstream
* Fri Nov 24 2023 zhangyao<zhangyao108@huawei.com> - 0.5.1-3
- sync patchs from upstream
- sync patches from upstream
* Mon Oct 30 2023 zhangyao<zhangyao108@huawei.com> - 0.5.1-2
- add simulate_udev.sh file