Skip to content

Commit 271aed8

Browse files
committed
unittest: net: eliminate mocking
There was a very elaborate mocking setup in the net device code involving `cfg(not(test))`, but the only point of it all was to be able to test the scenario where `tap.write_iovec` or `tap.read` return an error. We do not need mocking to achieve this though: We can simply close the tap fd. Thus remove all the mocking, and update the negative tests to close the fd. I had half a mind to just delete the tests, as currently we are not sensibly handling errors in device emulation anyway, so the assertions these tests make aren't exactly useful. However, once we implement device reset, this will probably change, so let's keep the tests. Signed-off-by: Patrick Roy <[email protected]>
1 parent 1d0a725 commit 271aed8

File tree

3 files changed

+11
-84
lines changed

3 files changed

+11
-84
lines changed

src/vmm/src/devices/virtio/net/device.rs

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
// Use of this source code is governed by a BSD-style license that can be
66
// found in the THIRD-PARTY file.
77

8-
#[cfg(not(test))]
98
use std::io::Read;
109
use std::mem;
1110
use std::net::Ipv4Addr;
@@ -716,12 +715,10 @@ impl Net {
716715
self.tx_rate_limiter.update_buckets(tx_bytes, tx_ops);
717716
}
718717

719-
#[cfg(not(test))]
720718
fn read_tap(&mut self) -> std::io::Result<usize> {
721719
self.tap.read(&mut self.rx_frame_buf)
722720
}
723721

724-
#[cfg(not(test))]
725722
fn write_tap(tap: &mut Tap, buf: &IoVecBuffer) -> std::io::Result<usize> {
726723
tap.write_iovec(buf)
727724
}
@@ -932,11 +929,11 @@ impl VirtioDevice for Net {
932929
#[cfg(test)]
933930
#[macro_use]
934931
pub mod tests {
935-
use std::io::Read;
936932
use std::net::Ipv4Addr;
933+
use std::os::fd::AsRawFd;
937934
use std::str::FromStr;
938935
use std::time::Duration;
939-
use std::{io, mem, thread};
936+
use std::{mem, thread};
940937

941938
use utils::net::mac::{MacAddr, MAC_ADDR_LEN};
942939

@@ -949,8 +946,8 @@ pub mod tests {
949946
};
950947
use crate::devices::virtio::net::test_utils::test::TestHelper;
951948
use crate::devices::virtio::net::test_utils::{
952-
default_net, if_index, inject_tap_tx_frame, set_mac, NetEvent, NetQueue, ReadTapMock,
953-
TapTrafficSimulator, WriteTapMock,
949+
default_net, if_index, inject_tap_tx_frame, set_mac, NetEvent, NetQueue,
950+
TapTrafficSimulator,
954951
};
955952
use crate::devices::virtio::net::NET_QUEUE_SIZES;
956953
use crate::devices::virtio::queue::VIRTQ_DESC_F_WRITE;
@@ -961,28 +958,6 @@ pub mod tests {
961958
use crate::rate_limiter::{BucketUpdate, RateLimiter, TokenBucket, TokenType};
962959
use crate::vstate::memory::{Address, GuestMemory};
963960

964-
impl Net {
965-
pub(crate) fn read_tap(&mut self) -> io::Result<usize> {
966-
match &self.tap.mocks.read_tap {
967-
ReadTapMock::Failure => Err(io::Error::new(
968-
io::ErrorKind::Other,
969-
"Read tap synthetically failed.",
970-
)),
971-
ReadTapMock::TapFrame => self.tap.read(&mut self.rx_frame_buf),
972-
}
973-
}
974-
975-
pub(crate) fn write_tap(tap: &mut Tap, buf: &IoVecBuffer) -> io::Result<usize> {
976-
match tap.mocks.write_tap {
977-
WriteTapMock::Success => tap.write_iovec(buf),
978-
WriteTapMock::Failure => Err(io::Error::new(
979-
io::ErrorKind::Other,
980-
"Write tap mock failure.",
981-
)),
982-
}
983-
}
984-
}
985-
986961
#[test]
987962
fn test_vnet_helpers() {
988963
let mut frame_buf = vec![42u8; vnet_hdr_len() - 1];
@@ -1212,7 +1187,6 @@ pub mod tests {
12121187
fn test_rx_retry() {
12131188
let mut th = TestHelper::get_default();
12141189
th.activate_net();
1215-
th.net().tap.mocks.set_read_tap(ReadTapMock::TapFrame);
12161190

12171191
// Add invalid descriptor chain - read only descriptor.
12181192
th.add_desc_chain(
@@ -1263,7 +1237,6 @@ pub mod tests {
12631237
fn test_rx_complex_desc_chain() {
12641238
let mut th = TestHelper::get_default();
12651239
th.activate_net();
1266-
th.net().tap.mocks.set_read_tap(ReadTapMock::TapFrame);
12671240

12681241
// Create a valid Rx avail descriptor chain with multiple descriptors.
12691242
th.add_desc_chain(
@@ -1302,7 +1275,6 @@ pub mod tests {
13021275
fn test_rx_multiple_frames() {
13031276
let mut th = TestHelper::get_default();
13041277
th.activate_net();
1305-
th.net().tap.mocks.set_read_tap(ReadTapMock::TapFrame);
13061278

13071279
// Create 2 valid Rx avail descriptor chains. Each one has enough space to fit the
13081280
// following 2 frames. But only 1 frame has to be written to each chain.
@@ -1525,7 +1497,9 @@ pub mod tests {
15251497
fn test_tx_tap_failure() {
15261498
let mut th = TestHelper::get_default();
15271499
th.activate_net();
1528-
th.net().tap.mocks.set_write_tap(WriteTapMock::Failure);
1500+
// force the next write to the tap to return an error by simply closing the fd
1501+
// SAFETY: its a valid fd
1502+
unsafe { libc::close(th.net.lock().unwrap().tap.as_raw_fd()) };
15291503

15301504
let desc_list = [(0, 1000, 0)];
15311505
th.add_desc_chain(NetQueue::Tx, 0, &desc_list);
@@ -1725,7 +1699,9 @@ pub mod tests {
17251699
fn test_read_tap_fail_event_handler() {
17261700
let mut th = TestHelper::get_default();
17271701
th.activate_net();
1728-
th.net().tap.mocks.set_read_tap(ReadTapMock::Failure);
1702+
// force the next write to the tap to return an error by simply closing the fd
1703+
// SAFETY: its a valid fd
1704+
unsafe { libc::close(th.net.lock().unwrap().tap.as_raw_fd()) };
17291705

17301706
// The RX queue is empty and rx_deffered_frame is set.
17311707
th.net().rx_deferred_frame = true;
@@ -1753,7 +1729,6 @@ pub mod tests {
17531729
fn test_deferred_frame() {
17541730
let mut th = TestHelper::get_default();
17551731
th.activate_net();
1756-
th.net().tap.mocks.set_read_tap(ReadTapMock::TapFrame);
17571732

17581733
let rx_packets_count = th.net().metrics.rx_packets_count.count();
17591734
let _ = inject_tap_tx_frame(&th.net(), 1000);

src/vmm/src/devices/virtio/net/tap.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ use utils::{ioctl_ioc_nr, ioctl_iow_nr};
1616

1717
use crate::devices::virtio::iovec::IoVecBuffer;
1818
use crate::devices::virtio::net::gen;
19-
#[cfg(test)]
20-
use crate::devices::virtio::net::test_utils::Mocks;
2119

2220
// As defined in the Linux UAPI:
2321
// https://elixir.bootlin.com/linux/v4.17/source/include/uapi/linux/if.h#L33
@@ -53,9 +51,6 @@ ioctl_iow_nr!(TUNSETVNETHDRSZ, TUNTAP, 216, ::std::os::raw::c_int);
5351
pub struct Tap {
5452
tap_file: File,
5553
pub(crate) if_name: [u8; IFACE_NAME_MAX_LEN],
56-
57-
#[cfg(test)]
58-
pub(crate) mocks: Mocks,
5954
}
6055

6156
// Returns a byte vector representing the contents of a null terminated C string which
@@ -149,9 +144,6 @@ impl Tap {
149144
tap_file: tuntap,
150145
// SAFETY: Safe since only the name is accessed, and it's cloned out.
151146
if_name: unsafe { ifreq.ifr_ifrn.ifrn_name },
152-
153-
#[cfg(test)]
154-
mocks: Mocks::default(),
155147
})
156148
}
157149

@@ -278,7 +270,6 @@ pub mod tests {
278270
let faulty_tap = Tap {
279271
tap_file: unsafe { File::from_raw_fd(-2) },
280272
if_name: [0x01; 16],
281-
mocks: Default::default(),
282273
};
283274
assert_eq!(
284275
faulty_tap.set_vnet_hdr_size(16).unwrap_err().to_string(),

src/vmm/src/devices/virtio/net/test_utils.rs

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -76,44 +76,6 @@ pub fn default_net_no_mmds() -> Net {
7676
net
7777
}
7878

79-
#[derive(Debug)]
80-
pub enum ReadTapMock {
81-
Failure,
82-
TapFrame,
83-
}
84-
85-
#[derive(Debug)]
86-
pub enum WriteTapMock {
87-
Failure,
88-
Success,
89-
}
90-
91-
// Used to simulate tap read and write fails in tests.
92-
#[derive(Debug)]
93-
pub struct Mocks {
94-
pub(crate) read_tap: ReadTapMock,
95-
pub(crate) write_tap: WriteTapMock,
96-
}
97-
98-
impl Mocks {
99-
pub fn set_read_tap(&mut self, read_tap: ReadTapMock) {
100-
self.read_tap = read_tap;
101-
}
102-
103-
pub fn set_write_tap(&mut self, write_tap: WriteTapMock) {
104-
self.write_tap = write_tap;
105-
}
106-
}
107-
108-
impl Default for Mocks {
109-
fn default() -> Mocks {
110-
Mocks {
111-
read_tap: ReadTapMock::TapFrame,
112-
write_tap: WriteTapMock::Success,
113-
}
114-
}
115-
}
116-
11779
#[derive(Debug)]
11880
pub enum NetQueue {
11981
Rx,
@@ -347,7 +309,7 @@ pub mod test {
347309
use crate::devices::virtio::net::device::vnet_hdr_len;
348310
use crate::devices::virtio::net::gen::ETH_HLEN;
349311
use crate::devices::virtio::net::test_utils::{
350-
assign_queues, default_net, inject_tap_tx_frame, NetEvent, NetQueue, ReadTapMock,
312+
assign_queues, default_net, inject_tap_tx_frame, NetEvent, NetQueue,
351313
};
352314
use crate::devices::virtio::net::{Net, MAX_BUFFER_SIZE, RX_INDEX, TX_INDEX};
353315
use crate::devices::virtio::queue::{VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE};
@@ -476,7 +438,6 @@ pub mod test {
476438

477439
/// Generate a tap frame of `frame_len` and check that it is deferred
478440
pub fn check_rx_deferred_frame(&mut self, frame_len: usize) -> Vec<u8> {
479-
self.net().tap.mocks.set_read_tap(ReadTapMock::TapFrame);
480441
let used_idx = self.rxq.used.idx.get();
481442

482443
// Inject frame to tap and run epoll.

0 commit comments

Comments
 (0)