diff --git a/coverage_config_x86_64.json b/coverage_config_x86_64.json index 425cd4f..58619aa 100644 --- a/coverage_config_x86_64.json +++ b/coverage_config_x86_64.json @@ -1,5 +1,5 @@ { - "coverage_score": 87.2, + "coverage_score": 85.5, "exclude_path": "", "crate_features": "" } diff --git a/i2c/Cargo.toml b/i2c/Cargo.toml index 1164740..3b96cd5 100644 --- a/i2c/Cargo.toml +++ b/i2c/Cargo.toml @@ -12,7 +12,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -clap = { version = "=3.0.0-beta.2", features = ["yaml"] } +clap = { version = ">=3.0", features = ["derive"] } env_logger = ">=0.9" libc = ">=0.2.95" log = ">=0.4.6" diff --git a/i2c/src/cli.yaml b/i2c/src/cli.yaml deleted file mode 100644 index 8a5933f..0000000 --- a/i2c/src/cli.yaml +++ /dev/null @@ -1,37 +0,0 @@ -name: vhost-device-i2c -version: "0.1.0" -author: "Viresh Kumar " -about: Virtio I2C backend daemon. - -settings: - - ArgRequiredElseHelp - -args: - # Connection to sockets - - socket_path: - short: s - long: socket-path - value_name: FILE - takes_value: true - about: Location of vhost-user Unix domain socket. This is suffixed by 0,1,2..socket_count-1. - - socket_count: - short: c - long: socket-count - value_name: INT - takes_value: true - about: Number of guests (sockets) to connect to. Default = 1. - # I2C device list on host - - devices: - short: l - long: device-list - value_name: PATH - takes_value: true - about: List of I2C bus and clients in format :[:][,:[:]] - -groups: - - required_args: - args: - - socket_path - args: - - devices - required: true diff --git a/i2c/src/main.rs b/i2c/src/main.rs index 81fd9c8..8218744 100644 --- a/i2c/src/main.rs +++ b/i2c/src/main.rs @@ -14,7 +14,7 @@ use std::num::ParseIntError; use std::sync::{Arc, RwLock}; use std::thread::spawn; -use clap::{load_yaml, App, ArgMatches}; +use clap::Parser; use thiserror::Error as ThisError; use vhost::{vhost_user, vhost_user::Listener}; use vhost_user_backend::VhostUserDaemon; @@ -28,8 +28,6 @@ type Result = std::result::Result; #[derive(Debug, PartialEq, ThisError)] /// Errors related to low level i2c helpers pub enum Error { - #[error("Invalid socket path")] - SocketPathInvalid, #[error("Invalid socket count: {0}")] SocketCountInvalid(usize), #[error("Invalid device list")] @@ -48,6 +46,23 @@ pub enum Error { FailedJoiningThreads, } +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct I2cArgs { + /// Location of vhost-user Unix domain socket. This is suffixed by 0,1,2..socket_count-1. + #[clap(short, long)] + socket_path: String, + + /// Number of guests (sockets) to connect to. + #[clap(short = 'c', long, default_value_t = 1)] + socket_count: usize, + + /// List of I2C bus and clients in format + /// :[:][,:[:]]. + #[clap(short = 'l', long)] + device_list: String, +} + #[derive(Debug, PartialEq)] struct DeviceConfig { adapter_no: u32, @@ -140,39 +155,25 @@ struct I2cConfiguration { devices: AdapterConfig, } -impl TryFrom for I2cConfiguration { +impl TryFrom for I2cConfiguration { type Error = Error; - fn try_from(cmd_args: ArgMatches) -> Result { - let socket_path = cmd_args - .value_of("socket_path") - .ok_or(Error::SocketPathInvalid)? - .to_string(); - - let socket_count = cmd_args - .value_of("socket_count") - .unwrap_or("1") - .parse::() - .map_err(Error::ParseFailure)?; - - if socket_count == 0 { + fn try_from(args: I2cArgs) -> Result { + if args.socket_count == 0 { return Err(Error::SocketCountInvalid(0)); } - let list = cmd_args - .value_of("devices") - .ok_or(Error::DeviceListInvalid)?; - let devices = AdapterConfig::try_from(list)?; + let devices = AdapterConfig::try_from(args.device_list.as_str())?; Ok(I2cConfiguration { - socket_path, - socket_count, + socket_path: args.socket_path, + socket_count: args.socket_count, devices, }) } } -fn start_backend(cmd_args: ArgMatches) -> Result<()> { - let config = I2cConfiguration::try_from(cmd_args).unwrap(); +fn start_backend(args: I2cArgs) -> Result<()> { + let config = I2cConfiguration::try_from(args).unwrap(); // The same i2c_map structure instance is shared between all the guests let i2c_map = Arc::new(I2cMap::::new(&config.devices).map_err(Error::I2cFailure)?); @@ -237,10 +238,7 @@ fn start_backend(cmd_args: ArgMatches) -> fn main() -> Result<()> { env_logger::init(); - let yaml = load_yaml!("cli.yaml"); - let cmd_args = App::from(yaml).get_matches(); - - start_backend::(cmd_args) + start_backend::(I2cArgs::parse()) } #[cfg(test)] @@ -260,19 +258,12 @@ mod tests { } } - fn get_cmd_args(name: Option<&str>, devices: &str, count: Option<&str>) -> ArgMatches { - let mut args = vec!["prog", "-l", devices]; - let yaml = load_yaml!("cli.yaml"); - let app = App::from(yaml); - - if let Some(name) = name { - args.extend_from_slice(&["-s", name]); + fn get_cmd_args(path: &str, devices: &str, count: usize) -> I2cArgs { + I2cArgs { + socket_path: path.to_string(), + socket_count: count, + device_list: devices.to_string(), } - - if let Some(count) = count { - args.extend_from_slice(&["-c", count]); - } - app.try_get_matches_from(args).unwrap() } #[test] @@ -296,45 +287,31 @@ mod tests { #[test] fn test_parse_failure() { - let socket_name = Some("vi2c.sock"); + let socket_name = "vi2c.sock"; // Invalid bus_addr - let cmd_args = get_cmd_args(socket_name, "1:4,3d:5", Some("5")); + let cmd_args = get_cmd_args(socket_name, "1:4,3d:5", 5); assert_eq!( I2cConfiguration::try_from(cmd_args).unwrap_err(), Error::ParseFailure("3d".parse::().unwrap_err()) ); // Invalid client address - let cmd_args = get_cmd_args(socket_name, "1:4d", Some("5")); + let cmd_args = get_cmd_args(socket_name, "1:4d", 5); assert_eq!( I2cConfiguration::try_from(cmd_args).unwrap_err(), Error::ParseFailure("4d".parse::().unwrap_err()) ); - // Invalid socket path - let cmd_args = get_cmd_args(None, "1:4d", Some("5")); - assert_eq!( - I2cConfiguration::try_from(cmd_args).unwrap_err(), - Error::SocketPathInvalid - ); - - // Invalid socket count - let cmd_args = get_cmd_args(socket_name, "1:4", Some("1d")); - assert_eq!( - I2cConfiguration::try_from(cmd_args).unwrap_err(), - Error::ParseFailure("1d".parse::().unwrap_err()) - ); - // Zero socket count - let cmd_args = get_cmd_args(socket_name, "1:4", Some("0")); + let cmd_args = get_cmd_args(socket_name, "1:4", 0); assert_eq!( I2cConfiguration::try_from(cmd_args).unwrap_err(), Error::SocketCountInvalid(0) ); // Duplicate client address: 4 - let cmd_args = get_cmd_args(socket_name, "1:4,2:32:21,5:4:23", Some("5")); + let cmd_args = get_cmd_args(socket_name, "1:4,2:32:21,5:4:23", 5); assert_eq!( I2cConfiguration::try_from(cmd_args).unwrap_err(), Error::ClientAddressDuplicate(4) @@ -343,14 +320,9 @@ mod tests { #[test] fn test_parse_successful() { - let socket_name = Some("vi2c.sock"); + let socket_name = "vi2c.sock"; - // Missing socket count, default (1) should be used. - let cmd_args = get_cmd_args(socket_name, "1:4,2:32:21,5:5:23", None); - let config = I2cConfiguration::try_from(cmd_args).unwrap(); - assert_eq!(config.socket_count, 1); - - let cmd_args = get_cmd_args(socket_name, "1:4,2:32:21,5:5:23", Some("5")); + let cmd_args = get_cmd_args(socket_name, "1:4,2:32:21,5:5:23", 5); let config = I2cConfiguration::try_from(cmd_args).unwrap(); let expected_devices = AdapterConfig::new_with(vec![ @@ -361,7 +333,7 @@ mod tests { let expected_config = I2cConfiguration { socket_count: 5, - socket_path: String::from(socket_name.unwrap()), + socket_path: String::from(socket_name), devices: expected_devices, }; @@ -387,8 +359,8 @@ mod tests { #[test] fn test_fail_listener() { // This will fail the listeners and thread will panic. - let socket_name = Some("~/path/not/present/i2c"); - let cmd_args = get_cmd_args(socket_name, "1:4,3:5", Some("5")); + let socket_name = "~/path/not/present/i2c"; + let cmd_args = get_cmd_args(socket_name, "1:4,3:5", 5); assert_eq!( start_backend::(cmd_args).unwrap_err(), diff --git a/rust-vmm-ci b/rust-vmm-ci index d023262..d216a46 160000 --- a/rust-vmm-ci +++ b/rust-vmm-ci @@ -1 +1 @@ -Subproject commit d023262164ef8766ac2b0be33de13ef52b8706a1 +Subproject commit d216a46879096a4f1e83af3a7b6c90c26e1a688d