mirror of
https://github.com/rust-vmm/vhost-device.git
synced 2025-12-29 17:09:25 +00:00
[i2c] Add more failure tests
Add more failure tests and check that the return error matches the expected error value. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
This commit is contained in:
parent
426050a877
commit
97e58e8201
@ -297,7 +297,7 @@ pub struct I2cReq {
|
||||
/// functionality without the need of a physical device.
|
||||
pub trait I2cDevice {
|
||||
// Open the device specified by the adapter number.
|
||||
fn open(adapter_no: u32) -> Result<Self>
|
||||
fn open(device_path: &str, adapter_no: u32) -> Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
@ -319,14 +319,14 @@ pub trait I2cDevice {
|
||||
|
||||
/// A physical I2C device. This structure can only be initialized on hosts
|
||||
/// where `/dev/i2c-XX` is available.
|
||||
#[derive(Debug)]
|
||||
pub struct PhysDevice {
|
||||
file: File,
|
||||
adapter_no: u32,
|
||||
}
|
||||
|
||||
impl I2cDevice for PhysDevice {
|
||||
fn open(adapter_no: u32) -> Result<Self> {
|
||||
let device_path = format!("/dev/i2c-{}", adapter_no);
|
||||
fn open(device_path: &str, adapter_no: u32) -> Result<Self> {
|
||||
Ok(PhysDevice {
|
||||
file: OpenOptions::new()
|
||||
.read(true)
|
||||
@ -418,6 +418,7 @@ impl I2cDevice for PhysDevice {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct I2cAdapter<D: I2cDevice> {
|
||||
device: D,
|
||||
adapter_no: u32,
|
||||
@ -512,9 +513,13 @@ impl<D: I2cDevice> I2cMap<D> {
|
||||
{
|
||||
let mut device_map = HashMap::new();
|
||||
let mut adapters: Vec<I2cAdapter<D>> = Vec::new();
|
||||
let prefix = "/dev/i2c-";
|
||||
|
||||
for (i, device_cfg) in device_config.inner.iter().enumerate() {
|
||||
let device = D::open(device_cfg.adapter_no)?;
|
||||
let device = D::open(
|
||||
&format!("{}{}", prefix, device_cfg.adapter_no),
|
||||
device_cfg.adapter_no,
|
||||
)?;
|
||||
let adapter = I2cAdapter::new(device)?;
|
||||
|
||||
// Check that all addresses corresponding to the adapter are valid.
|
||||
@ -561,6 +566,7 @@ impl<D: I2cDevice> I2cMap<D> {
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use std::convert::TryFrom;
|
||||
use vmm_sys_util::tempfile::TempFile;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DummyDevice {
|
||||
@ -584,7 +590,7 @@ pub mod tests {
|
||||
}
|
||||
|
||||
impl I2cDevice for DummyDevice {
|
||||
fn open(adapter_no: u32) -> Result<Self>
|
||||
fn open(_path: &str, adapter_no: u32) -> Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
@ -630,6 +636,15 @@ pub mod tests {
|
||||
};
|
||||
let adapter = I2cAdapter::new(i2c_device).unwrap();
|
||||
assert_eq!(adapter.smbus, false);
|
||||
|
||||
let i2c_device = DummyDevice {
|
||||
funcs_result: Ok(0),
|
||||
..Default::default()
|
||||
};
|
||||
assert_eq!(
|
||||
I2cAdapter::new(i2c_device).unwrap_err(),
|
||||
Error::AdapterFunctionInvalid(0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -701,12 +716,59 @@ pub mod tests {
|
||||
i2c_map.transfer(&mut reqs).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transfer_failure() {
|
||||
let adapter_config = AdapterConfig::try_from("1:3").unwrap();
|
||||
let mut i2c_map: I2cMap<DummyDevice> = I2cMap::new(&adapter_config).unwrap();
|
||||
|
||||
i2c_map.adapters[0].smbus = false;
|
||||
|
||||
let mut reqs: Vec<I2cReq> = vec![I2cReq {
|
||||
// Will cause failure
|
||||
addr: 0x4,
|
||||
flags: 0,
|
||||
len: 2,
|
||||
buf: vec![7, 4],
|
||||
}];
|
||||
|
||||
assert_eq!(
|
||||
i2c_map.transfer(&mut reqs).unwrap_err(),
|
||||
Error::ClientAddressInvalid
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_smbus_transfer_failure() {
|
||||
let adapter_config = AdapterConfig::try_from("1:3").unwrap();
|
||||
let mut i2c_map: I2cMap<DummyDevice> = I2cMap::new(&adapter_config).unwrap();
|
||||
i2c_map.adapters[0].smbus = true;
|
||||
|
||||
// I2C_SMBUS_READ (Invalid size) failure operation
|
||||
let mut reqs: Vec<I2cReq> = vec![I2cReq {
|
||||
addr: 0x3,
|
||||
flags: I2C_M_RD,
|
||||
// Will cause failure
|
||||
len: 2,
|
||||
buf: [34].to_vec(),
|
||||
}];
|
||||
assert_eq!(
|
||||
i2c_map.transfer(&mut reqs).unwrap_err(),
|
||||
Error::MessageLengthInvalid("read", 2)
|
||||
);
|
||||
|
||||
// I2C_SMBUS_WRITE (Invalid size) failure operation
|
||||
let mut reqs: Vec<I2cReq> = vec![I2cReq {
|
||||
addr: 0x3,
|
||||
flags: 0,
|
||||
// Will cause failure
|
||||
len: 4,
|
||||
buf: [34].to_vec(),
|
||||
}];
|
||||
assert_eq!(
|
||||
i2c_map.transfer(&mut reqs).unwrap_err(),
|
||||
Error::MessageLengthInvalid("write", 4)
|
||||
);
|
||||
|
||||
// I2C_SMBUS_READ (I2C_SMBUS_WORD_DATA) failure operation
|
||||
let mut reqs: Vec<I2cReq> = vec![
|
||||
I2cReq {
|
||||
@ -790,5 +852,83 @@ pub mod tests {
|
||||
i2c_map.transfer(&mut reqs).unwrap_err(),
|
||||
Error::SMBusTransferInvalid(2, 1, 3)
|
||||
);
|
||||
|
||||
// I2C_SMBUS_READ (Invalid request count) failure operation
|
||||
let mut reqs = vec![
|
||||
I2cReq {
|
||||
addr: 0x3,
|
||||
flags: 0,
|
||||
len: 1,
|
||||
buf: [34].to_vec(),
|
||||
},
|
||||
I2cReq {
|
||||
addr: 0x3,
|
||||
flags: I2C_M_RD,
|
||||
len: 2,
|
||||
buf: [3, 4].to_vec(),
|
||||
},
|
||||
// Will cause failure
|
||||
I2cReq {
|
||||
addr: 0,
|
||||
flags: 0,
|
||||
len: 0,
|
||||
buf: [0].to_vec(),
|
||||
},
|
||||
];
|
||||
assert_eq!(
|
||||
i2c_map.transfer(&mut reqs).unwrap_err(),
|
||||
Error::SMBusTransferInvalid(3, 1, 2)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_phys_device_failure() {
|
||||
// Open failure
|
||||
assert_eq!(
|
||||
PhysDevice::open("/dev/i2c-invalid-path", 0).unwrap_err(),
|
||||
Error::DeviceOpenFailed(0)
|
||||
);
|
||||
|
||||
let file = TempFile::new().unwrap();
|
||||
let mut dev = PhysDevice::open(file.as_path().to_str().unwrap(), 1).unwrap();
|
||||
|
||||
// Match adapter number
|
||||
assert_eq!(dev.adapter_no(), 1);
|
||||
|
||||
// funcs failure
|
||||
assert_eq!(
|
||||
dev.funcs().unwrap_err(),
|
||||
Error::IoctlFailure("funcs", IoError::last())
|
||||
);
|
||||
|
||||
// rdwr failure
|
||||
let mut reqs = [I2cReq {
|
||||
addr: 0x4,
|
||||
flags: 0,
|
||||
len: 2,
|
||||
buf: vec![7, 4],
|
||||
}];
|
||||
assert_eq!(
|
||||
dev.rdwr(&mut reqs).unwrap_err(),
|
||||
Error::IoctlFailure("rdwr", IoError::last())
|
||||
);
|
||||
|
||||
// smbus failure
|
||||
let mut data = SmbusMsg {
|
||||
read_write: 0,
|
||||
command: 0,
|
||||
size: 0,
|
||||
data: None,
|
||||
};
|
||||
assert_eq!(
|
||||
dev.smbus(&mut data).unwrap_err(),
|
||||
Error::IoctlFailure("smbus", IoError::last())
|
||||
);
|
||||
|
||||
// slave failure
|
||||
assert_eq!(
|
||||
dev.slave(0).unwrap_err(),
|
||||
Error::IoctlFailure("slave", IoError::last())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,39 +256,62 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_cmd_args(name: &str, devices: &str, count: Option<u32>) -> ArgMatches {
|
||||
let mut args = vec!["prog", "-s", name, "-l", devices];
|
||||
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);
|
||||
let socket_count_str;
|
||||
|
||||
if let Some(name) = name {
|
||||
args.extend_from_slice(&["-s", &name]);
|
||||
}
|
||||
|
||||
if let Some(count) = count {
|
||||
socket_count_str = count.to_string();
|
||||
args.extend_from_slice(&["-c", &socket_count_str]);
|
||||
args.extend_from_slice(&["-c", &count]);
|
||||
}
|
||||
app.try_get_matches_from(args).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_failure() {
|
||||
let socket_name = "vi2c.sock";
|
||||
let socket_name = Some("vi2c.sock");
|
||||
|
||||
// Invalid device list
|
||||
let cmd_args = get_cmd_args(socket_name, "1:4d", Some(5));
|
||||
// Invalid bus_addr
|
||||
let cmd_args = get_cmd_args(socket_name, "1:4,3d:5", Some("5"));
|
||||
assert_eq!(
|
||||
I2cConfiguration::try_from(cmd_args).unwrap_err(),
|
||||
Error::ParseFailure("4d".parse::<u32>().unwrap_err())
|
||||
Error::ParseFailure("3d".parse::<u32>().unwrap_err())
|
||||
);
|
||||
|
||||
// Invalid client address
|
||||
let cmd_args = get_cmd_args(socket_name, "1:4d", Some("5"));
|
||||
assert_eq!(
|
||||
I2cConfiguration::try_from(cmd_args).unwrap_err(),
|
||||
Error::ParseFailure("4d".parse::<u16>().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(0));
|
||||
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::<u16>().unwrap_err())
|
||||
);
|
||||
|
||||
// Zero socket count
|
||||
let cmd_args = get_cmd_args(socket_name, "1:4", Some("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", Some("5"));
|
||||
assert_eq!(
|
||||
I2cConfiguration::try_from(cmd_args).unwrap_err(),
|
||||
Error::ClientAddressDuplicate(4)
|
||||
@ -297,14 +320,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_successful() {
|
||||
let socket_name = "vi2c.sock";
|
||||
let socket_name = Some("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", Some("5"));
|
||||
let config = I2cConfiguration::try_from(cmd_args).unwrap();
|
||||
|
||||
let expected_devices = AdapterConfig::new_with(vec![
|
||||
@ -315,7 +338,7 @@ mod tests {
|
||||
|
||||
let expected_config = I2cConfiguration {
|
||||
socket_count: 5,
|
||||
socket_path: String::from(socket_name),
|
||||
socket_path: String::from(socket_name.unwrap()),
|
||||
devices: expected_devices,
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user