1
Fork 0

more epoll test cleanup

This commit is contained in:
Ralf Jung 2024-08-16 16:58:49 +02:00
parent edd1efb136
commit 9184eb54ea

View file

@ -24,10 +24,7 @@ fn main() {
const EPOLL_IN_OUT_ET: u32 = (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _;
#[track_caller]
fn check_epoll_wait<const N: usize>(
epfd: i32,
mut expected_notifications: Vec<(u32, u64)>,
) -> bool {
fn check_epoll_wait<const N: usize>(epfd: i32, expected_notifications: &[(u32, u64)]) -> bool {
let epoll_event = libc::epoll_event { events: 0, u64: 0 };
let mut array: [libc::epoll_event; N] = [epoll_event; N];
let maxsize = N;
@ -39,8 +36,9 @@ fn check_epoll_wait<const N: usize>(
assert_eq!(res, expected_notifications.len().try_into().unwrap());
let slice = unsafe { std::slice::from_raw_parts(array_ptr, res.try_into().unwrap()) };
let mut return_events = slice.iter();
let mut expected_notifications = expected_notifications.iter();
while let Some(return_event) = return_events.next() {
if let Some(notification) = expected_notifications.pop() {
if let Some(notification) = expected_notifications.next() {
let event = return_event.events;
let data = return_event.u64;
assert_eq!(event, notification.0);
@ -49,10 +47,8 @@ fn check_epoll_wait<const N: usize>(
return false;
}
}
if !expected_notifications.is_empty() {
return false;
}
return true;
// There shouldn't be any more expected.
return expected_notifications.next().is_none();
}
fn test_epoll_socketpair() {
@ -81,10 +77,10 @@ fn test_epoll_socketpair() {
// Check result from epoll_wait.
let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
let expected_value = u64::try_from(fds[1]).unwrap();
assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
// Check that this is indeed using "ET" (edge-trigger) semantics: a second epoll should return nothing.
assert!(check_epoll_wait::<8>(epfd, vec![]));
assert!(check_epoll_wait::<8>(epfd, &[]));
// Write some more to fd[0].
let data = "abcde".as_bytes().as_ptr();
@ -93,7 +89,7 @@ fn test_epoll_socketpair() {
// This did not change the readiness of fd[1]. And yet, we're seeing the event reported
// again by the kernel, so Miri does the same.
assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
// Close the peer socketpair.
let res = unsafe { libc::close(fds[0]) };
@ -102,7 +98,7 @@ fn test_epoll_socketpair() {
// Check result from epoll_wait.
let expected_event = u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT).unwrap();
let expected_value = u64::try_from(fds[1]).unwrap();
assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
}
fn test_epoll_ctl_mod() {
@ -129,7 +125,7 @@ fn test_epoll_ctl_mod() {
// Check result from epoll_wait.
let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
let expected_value = u64::try_from(fds[1]).unwrap();
assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
// Test EPOLLRDHUP.
let mut ev = libc::epoll_event {
@ -146,7 +142,7 @@ fn test_epoll_ctl_mod() {
// Check result from epoll_wait.
let expected_event = u32::try_from(libc::EPOLLRDHUP | libc::EPOLLIN | libc::EPOLLOUT).unwrap();
let expected_value = u64::try_from(fds[1]).unwrap();
assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
}
fn test_epoll_ctl_del() {
@ -170,7 +166,7 @@ fn test_epoll_ctl_del() {
assert_ne!(res, -1);
// Test EPOLL_CTL_DEL.
assert!(check_epoll_wait::<0>(epfd, vec![]));
assert!(check_epoll_wait::<0>(epfd, &[]));
}
// This test is for one fd registered under two different epoll instance.
@ -201,8 +197,8 @@ fn test_two_epoll_instance() {
// Notification should be received from both instance of epoll.
let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
let expected_value = u64::try_from(fds[1]).unwrap();
assert!(check_epoll_wait::<8>(epfd1, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd2, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd1, &[(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd2, &[(expected_event, expected_value)]));
}
// This test is for two same file description registered under the same epoll instance through dup.
@ -238,7 +234,7 @@ fn test_two_same_fd_in_same_epoll_instance() {
let expected_value = 5 as u64;
assert!(check_epoll_wait::<8>(
epfd,
vec![(expected_event, expected_value), (expected_event, expected_value)]
&[(expected_event, expected_value), (expected_event, expected_value)]
));
}
@ -264,7 +260,7 @@ fn test_epoll_eventfd() {
// Check result from epoll_wait.
let expected_event = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap();
let expected_value = u64::try_from(fd).unwrap();
assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
}
fn test_pointer() {
@ -316,7 +312,7 @@ fn test_epoll_socketpair_both_sides() {
let expected_value1 = fds[1] as u64;
assert!(check_epoll_wait::<8>(
epfd,
vec![(expected_event1, expected_value1), (expected_event0, expected_value0)]
&[(expected_event0, expected_value0), (expected_event1, expected_value1)]
));
// Read from fds[0].
@ -328,7 +324,7 @@ fn test_epoll_socketpair_both_sides() {
// Notification should be provided for fds[1].
let expected_event = u32::try_from(libc::EPOLLOUT).unwrap();
let expected_value = fds[1] as u64;
assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
}
// When file description is fully closed, epoll_wait should not provide any notification for
@ -357,7 +353,7 @@ fn test_closed_fd() {
assert_eq!(res, 0);
// No notification should be provided because the file description is closed.
assert!(check_epoll_wait::<8>(epfd, vec![]));
assert!(check_epoll_wait::<8>(epfd, &[]));
}
// When a certain file descriptor registered with epoll is closed, but the underlying file description
@ -391,7 +387,7 @@ fn test_not_fully_closed_fd() {
// Notification should still be provided because the file description is not closed.
let expected_event = u32::try_from(libc::EPOLLOUT).unwrap();
let expected_value = fd as u64;
assert!(check_epoll_wait::<1>(epfd, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<1>(epfd, &[(expected_event, expected_value)]));
// Write to the eventfd instance to produce notification.
let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes();
@ -403,7 +399,7 @@ fn test_not_fully_closed_fd() {
assert_eq!(res, 0);
// No notification should be provided.
assert!(check_epoll_wait::<1>(epfd, vec![]));
assert!(check_epoll_wait::<1>(epfd, &[]));
}
// Each time a notification is provided, it should reflect the file description's readiness
@ -438,7 +434,7 @@ fn test_event_overwrite() {
// Check result from epoll_wait.
let expected_event = u32::try_from(libc::EPOLLOUT).unwrap();
let expected_value = u64::try_from(fd).unwrap();
assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
}
// An epoll notification will be provided for every succesful read in a socketpair.
@ -479,7 +475,7 @@ fn test_socketpair_read() {
let expected_value1 = fds[1] as u64;
assert!(check_epoll_wait::<8>(
epfd,
vec![(expected_event1, expected_value1), (expected_event0, expected_value0)]
&[(expected_event0, expected_value0), (expected_event1, expected_value1)]
));
// Read 3 bytes from fds[0].
@ -492,7 +488,7 @@ fn test_socketpair_read() {
// But in real system, no notification will be provided here.
let expected_event = u32::try_from(libc::EPOLLOUT).unwrap();
let expected_value = fds[1] as u64;
assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
// Read until the buffer is empty.
let mut buf: [u8; 2] = [0; 2];
@ -504,5 +500,5 @@ fn test_socketpair_read() {
// In real system, notification will be provided too.
let expected_event = u32::try_from(libc::EPOLLOUT).unwrap();
let expected_value = fds[1] as u64;
assert!(check_epoll_wait::<8>(epfd, vec![(expected_event, expected_value)]));
assert!(check_epoll_wait::<8>(epfd, &[(expected_event, expected_value)]));
}