From 57b96aa3a30abe3243340af087dcbff05d31a9bc Mon Sep 17 00:00:00 2001 From: Andreea Florescu Date: Tue, 26 Oct 2021 09:25:21 +0300 Subject: [PATCH] update I2cAdapter to allow setting a mock device Before the constructor of this function was opening the device corresponding to the passed path. This did not allow for properly mocking the device functionality. Now the device is passed as a parameter instead, which allows us to tweak what the device returns for ioctl calls, and we can thus test multiple scenarios. Signed-off-by: Andreea Florescu --- coverage_config_x86_64.json | 2 +- src/i2c/src/i2c.rs | 48 ++++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/coverage_config_x86_64.json b/coverage_config_x86_64.json index ff7665f..0d2723f 100644 --- a/coverage_config_x86_64.json +++ b/coverage_config_x86_64.json @@ -1,5 +1,5 @@ { - "coverage_score": 49.6, + "coverage_score": 48.8, "exclude_path": "", "crate_features": "" } diff --git a/src/i2c/src/i2c.rs b/src/i2c/src/i2c.rs index 47baa4c..561e90d 100644 --- a/src/i2c/src/i2c.rs +++ b/src/i2c/src/i2c.rs @@ -240,8 +240,8 @@ pub struct I2cReq { /// mock implementation for the I2C driver so that we can test the I2C /// functionality without the need of a physical device. pub trait I2cDevice { - // Open the device specified by path. - fn open(device_path: String) -> Result + // Open the device specified by the adapter number. + fn open(adapter_no: u32) -> Result where Self: Sized; @@ -256,21 +256,27 @@ pub trait I2cDevice { // Corresponds to the I2C_SLAVE ioctl call. fn slave(&self, addr: u64) -> i32; + + // Returns the adapter number corresponding to this device. + fn adapter_no(&self) -> u32; } /// A physical I2C device. This structure can only be initialized on hosts /// where `/dev/i2c-XX` is available. pub struct PhysDevice { file: File, + adapter_no: u32, } impl I2cDevice for PhysDevice { - fn open(device_path: String) -> Result { + fn open(adapter_no: u32) -> Result { + let device_path = format!("/dev/i2c-{}", adapter_no); Ok(PhysDevice { file: OpenOptions::new() .read(true) .write(true) .open(device_path)?, + adapter_no, }) } @@ -289,6 +295,10 @@ impl I2cDevice for PhysDevice { fn slave(&self, addr: u64) -> i32 { unsafe { ioctl(self.file.as_raw_fd(), I2C_SLAVE, addr as c_ulong) } } + + fn adapter_no(&self) -> u32 { + self.adapter_no + } } pub struct I2cAdapter { @@ -298,19 +308,16 @@ pub struct I2cAdapter { } impl I2cAdapter { - // Creates a new adapter corresponding to the specified number. - fn new(adapter_no: u32) -> Result> { - let i2cdev = format!("/dev/i2c-{}", adapter_no); + // Creates a new adapter corresponding to `device`. + fn new(mut device: D) -> Result> { let func: u64 = I2C_FUNC_SMBUS_ALL; - let mut device = D::open(i2cdev)?; - let smbus; - let ret = device.funcs(func); if ret == -1 { println!("Failed to get I2C function"); return errno_result(); } + let smbus; if (func & I2C_FUNC_I2C) != 0 { smbus = false; } else if (func & I2C_FUNC_SMBUS_ALL) != 0 { @@ -321,8 +328,8 @@ impl I2cAdapter { } Ok(I2cAdapter { + adapter_no: device.adapter_no(), device, - adapter_no, smbus, }) } @@ -436,7 +443,8 @@ impl I2cMap { let mut adapters: Vec> = Vec::new(); for (i, device_cfg) in device_config.inner.iter().enumerate() { - let adapter = I2cAdapter::new(device_cfg.adapter_no)?; + let device = D::open(device_cfg.adapter_no)?; + let adapter = I2cAdapter::new(device)?; // Check that all addresses corresponding to the adapter are valid. for addr in &device_cfg.addr { @@ -489,14 +497,18 @@ pub mod tests { rdwr_result: i32, smbus_result: i32, slave_result: i32, + adapter_no: u32, } impl I2cDevice for DummyDevice { - fn open(_device_path: String) -> Result + fn open(adapter_no: u32) -> Result where Self: Sized, { - Ok(DummyDevice::default()) + Ok(DummyDevice { + adapter_no, + ..Default::default() + }) } fn funcs(&mut self, _func: u64) -> i32 { @@ -514,6 +526,10 @@ pub mod tests { fn slave(&self, _addr: u64) -> i32 { self.slave_result } + + fn adapter_no(&self) -> u32 { + self.adapter_no + } } #[test] @@ -532,9 +548,9 @@ pub mod tests { let i2c_map: I2cMap = I2cMap::new(&adapter_config).unwrap(); assert_eq!(i2c_map.adapters.len(), 3); - assert_eq!(i2c_map.adapters[0].adapter_no, 1); - assert_eq!(i2c_map.adapters[1].adapter_no, 2); - assert_eq!(i2c_map.adapters[2].adapter_no, 5); + assert_eq!(i2c_map.adapters[0].adapter_no(), 1); + assert_eq!(i2c_map.adapters[1].adapter_no(), 2); + assert_eq!(i2c_map.adapters[2].adapter_no(), 5); assert_eq!(i2c_map.device_map[4], 0); assert_eq!(i2c_map.device_map[32], 1);