about summary refs log tree commit diff
path: root/src/tools/miri/tests
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-08-16 16:14:42 +0000
committerbors <bors@rust-lang.org>2024-08-16 16:14:42 +0000
commit83f1b380825d50e3cffe84ef4c39a09bf841a3c1 (patch)
treec70b68a567305becd89e4a26a0c37d07b7a2a370 /src/tools/miri/tests
parent1a51dd9247c5ecf9efa99ebf644bb12e33dcf3b5 (diff)
parent883e4773b30f652e83326df99dc0ec7d652e1f94 (diff)
downloadrust-83f1b380825d50e3cffe84ef4c39a09bf841a3c1.tar.gz
rust-83f1b380825d50e3cffe84ef4c39a09bf841a3c1.zip
Auto merge of #3809 - RalfJung:fd-refcell, r=oli-obk
FD: remove big surrounding RefCell, simplify socketpair

A while ago, I added the big implicit RefCell for all file descriptions since it avoided interior mutability in `eventfd`. However, this requires us to hold the RefCell "lock" around the entire invocation of the `read`/`write` methods on an FD, which is not great. For instance, if an FD wants to update epoll notifications from inside its `read`/`write`, it is very crucial that the notification check does not end up accessing the FD itself. Such cycles, however, occur naturally:
- eventfd wants to update notifications for itself
- socketfd wants to update notifications on its "peer", which will in turn check *its* peer to see whether that buffer is empty -- and my peer's peer is myself.

This then also lets us simplify socketpair, which currently holds a weak reference to its peer *and* a weak reference to the peer's buffer -- that was previously needed precisely to avoid this issue.
Diffstat (limited to 'src/tools/miri/tests')
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-epoll.rs243
1 files changed, 98 insertions, 145 deletions
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs b/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs
index 11a0257dc4e..841761e53dd 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-epoll.rs
@@ -5,34 +5,40 @@ use std::convert::TryInto;
 use std::mem::MaybeUninit;
 
 fn main() {
+    test_epoll_socketpair();
+    test_epoll_socketpair_both_sides();
+    test_socketpair_read();
+    test_epoll_eventfd();
+
     test_event_overwrite();
     test_not_fully_closed_fd();
     test_closed_fd();
-    test_epoll_socketpair_special_case();
     test_two_epoll_instance();
     test_epoll_ctl_mod();
-    test_epoll_socketpair();
-    test_epoll_eventfd();
     test_epoll_ctl_del();
     test_pointer();
     test_two_same_fd_in_same_epoll_instance();
-    test_socketpair_read();
 }
 
-fn check_epoll_wait<const N: usize>(
-    epfd: i32,
-    mut expected_notifications: Vec<(u32, u64)>,
-) -> bool {
+// Using `as` cast since `EPOLLET` wraps around
+const EPOLL_IN_OUT_ET: u32 = (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _;
+
+#[track_caller]
+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;
     let array_ptr = array.as_mut_ptr();
     let res = unsafe { libc::epoll_wait(epfd, array_ptr, maxsize.try_into().unwrap(), 0) };
+    if res < 0 {
+        panic!("epoll_wait failed: {}", std::io::Error::last_os_error());
+    }
     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);
@@ -41,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() {
@@ -54,21 +58,17 @@ fn test_epoll_socketpair() {
 
     // Create a socketpair instance.
     let mut fds = [-1, -1];
-    let mut res =
-        unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
+    let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
     assert_eq!(res, 0);
 
     // Write to fd[0]
     let data = "abcde".as_bytes().as_ptr();
-    res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() };
+    let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) };
     assert_eq!(res, 5);
 
-    // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET
-    // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32.
-    let epollet = libc::EPOLLET as u32;
-    let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLRDHUP).unwrap() | epollet;
+    // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP
     let mut ev = libc::epoll_event {
-        events: u32::try_from(flags).unwrap(),
+        events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET | libc::EPOLLRDHUP) as _,
         u64: u64::try_from(fds[1]).unwrap(),
     };
     let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
@@ -77,16 +77,29 @@ 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, &[]));
+
+    // Write some more to fd[0].
+    let data = "abcde".as_bytes().as_ptr();
+    let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) };
+    assert_eq!(res, 5);
+
+    // 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, &[(expected_event, expected_value)]));
 
     // Close the peer socketpair.
     let res = unsafe { libc::close(fds[0]) };
     assert_eq!(res, 0);
 
     // Check result from epoll_wait.
+    // We expect to get a read, write, HUP notification from the close since closing an FD always unblocks reads and writes on its peer.
     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() {
@@ -96,35 +109,28 @@ fn test_epoll_ctl_mod() {
 
     // Create a socketpair instance.
     let mut fds = [-1, -1];
-    let mut res =
-        unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
+    let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
     assert_eq!(res, 0);
 
     // Write to fd[0].
     let data = "abcde".as_bytes().as_ptr();
-    res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() };
+    let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) };
     assert_eq!(res, 5);
 
     // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET.
-    // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32.
-    let epollet = libc::EPOLLET as u32;
-    let mut flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet;
-    let mut ev = libc::epoll_event {
-        events: u32::try_from(flags).unwrap(),
-        u64: u64::try_from(fds[1]).unwrap(),
-    };
+    // (Not using checked cast as EPOLLET wraps around.)
+    let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fds[1]).unwrap() };
     let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
     assert_ne!(res, -1);
 
     // 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.
-    flags |= u32::try_from(libc::EPOLLRDHUP).unwrap();
     let mut ev = libc::epoll_event {
-        events: u32::try_from(flags).unwrap(),
+        events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET | libc::EPOLLRDHUP) as _,
         u64: u64::try_from(fds[1]).unwrap(),
     };
     let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_MOD, fds[1], &mut ev) };
@@ -137,7 +143,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() {
@@ -147,28 +153,21 @@ fn test_epoll_ctl_del() {
 
     // Create a socketpair instance.
     let mut fds = [-1, -1];
-    let mut res =
-        unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
+    let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
     assert_eq!(res, 0);
 
     // Write to fd[0]
     let data = "abcde".as_bytes().as_ptr();
-    res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() };
+    let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) };
     assert_eq!(res, 5);
 
     // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET
-    // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32.
-    let epollet = libc::EPOLLET as u32;
-    let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet;
-    let mut ev = libc::epoll_event {
-        events: u32::try_from(flags).unwrap(),
-        u64: u64::try_from(fds[1]).unwrap(),
-    };
+    let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fds[1]).unwrap() };
     let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
     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.
@@ -181,22 +180,16 @@ fn test_two_epoll_instance() {
 
     // Create a socketpair instance.
     let mut fds = [-1, -1];
-    let mut res =
-        unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
+    let res = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) };
     assert_eq!(res, 0);
 
     // Write to the socketpair.
     let data = "abcde".as_bytes().as_ptr();
-    res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() };
+    let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) };
     assert_eq!(res, 5);
 
     // Register one side of the socketpair with EPOLLIN | EPOLLOUT | EPOLLET.
-    let epollet = libc::EPOLLET as u32;
-    let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet;
-    let mut ev = libc::epoll_event {
-        events: u32::try_from(flags).unwrap(),
-        u64: u64::try_from(fds[1]).unwrap(),
-    };
+    let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fds[1]).unwrap() };
     let res = unsafe { libc::epoll_ctl(epfd1, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
     assert_ne!(res, -1);
     let res = unsafe { libc::epoll_ctl(epfd2, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
@@ -205,8 +198,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.
@@ -226,17 +219,15 @@ fn test_two_same_fd_in_same_epoll_instance() {
     assert_ne!(newfd, -1);
 
     // Register both fd to the same epoll instance.
-    let epollet = libc::EPOLLET as u32;
-    let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet;
-    let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: 5 as u64 };
-    let mut res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
+    let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: 5 as u64 };
+    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
     assert_ne!(res, -1);
-    res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, newfd, &mut ev) };
+    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, newfd, &mut ev) };
     assert_ne!(res, -1);
 
     // Write to the socketpair.
     let data = "abcde".as_bytes().as_ptr();
-    res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5).try_into().unwrap() };
+    let res = unsafe { libc::write(fds[0], data as *const libc::c_void, 5) };
     assert_eq!(res, 5);
 
     //Two notification should be received.
@@ -244,7 +235,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)]
     ));
 }
 
@@ -255,9 +246,7 @@ fn test_epoll_eventfd() {
 
     // Write to the eventfd instance.
     let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes();
-    let res: i32 = unsafe {
-        libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
-    };
+    let res = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8) };
     assert_eq!(res, 8);
 
     // Create an epoll instance.
@@ -265,20 +254,14 @@ fn test_epoll_eventfd() {
     assert_ne!(epfd, -1);
 
     // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
-    // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32.
-    let epollet = libc::EPOLLET as u32;
-    let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet;
-    let mut ev = libc::epoll_event {
-        events: u32::try_from(flags).unwrap(),
-        u64: u64::try_from(fd).unwrap(),
-    };
+    let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fd).unwrap() };
     let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) };
     assert_ne!(res, -1);
 
     // 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() {
@@ -292,20 +275,15 @@ fn test_pointer() {
     assert_eq!(res, 0);
 
     // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET
-    // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32.
-    let epollet = libc::EPOLLET as u32;
-    let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLRDHUP).unwrap() | epollet;
     let data = MaybeUninit::<u64>::uninit().as_ptr();
-    let mut ev = libc::epoll_event {
-        events: u32::try_from(flags).unwrap(),
-        u64: data.expose_provenance() as u64,
-    };
+    let mut ev =
+        libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: data.expose_provenance() as u64 };
     let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
     assert_ne!(res, -1);
 }
 
 // When read/write happened on one side of the socketpair, only the other side will be notified.
-fn test_epoll_socketpair_special_case() {
+fn test_epoll_socketpair_both_sides() {
     // Create an epoll instance.
     let epfd = unsafe { libc::epoll_create1(0) };
     assert_ne!(epfd, -1);
@@ -316,18 +294,16 @@ fn test_epoll_socketpair_special_case() {
     assert_eq!(res, 0);
 
     // Register both fd to the same epoll instance.
-    let epollet = libc::EPOLLET as u32;
-    let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet;
-    let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: fds[0] as u64 };
-    let mut res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) };
+    let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fds[0] as u64 };
+    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) };
     assert_ne!(res, -1);
-    let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: fds[1] as u64 };
-    res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
+    let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: fds[1] as u64 };
+    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
     assert_ne!(res, -1);
 
     // Write to fds[1].
     let data = "abcde".as_bytes().as_ptr();
-    res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5).try_into().unwrap() };
+    let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) };
     assert_eq!(res, 5);
 
     //Two notification should be received.
@@ -337,21 +313,19 @@ fn test_epoll_socketpair_special_case() {
     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].
     let mut buf: [u8; 5] = [0; 5];
-    res = unsafe {
-        libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap()
-    };
+    let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) };
     assert_eq!(res, 5);
     assert_eq!(buf, "abcde".as_bytes());
 
     // 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
@@ -366,21 +340,13 @@ fn test_closed_fd() {
     let fd = unsafe { libc::eventfd(0, flags) };
 
     // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
-    // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32.
-    let epollet = libc::EPOLLET as u32;
-    let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet;
-    let mut ev = libc::epoll_event {
-        events: u32::try_from(flags).unwrap(),
-        u64: u64::try_from(fd).unwrap(),
-    };
+    let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fd).unwrap() };
     let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) };
     assert_ne!(res, -1);
 
     // Write to the eventfd instance.
     let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes();
-    let res: i32 = unsafe {
-        libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
-    };
+    let res = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8) };
     assert_eq!(res, 8);
 
     // Close the eventfd.
@@ -388,7 +354,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
@@ -411,13 +377,7 @@ fn test_not_fully_closed_fd() {
     assert_ne!(newfd, -1);
 
     // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
-    // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32.
-    let epollet = libc::EPOLLET as u32;
-    let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet;
-    let mut ev = libc::epoll_event {
-        events: u32::try_from(flags).unwrap(),
-        u64: u64::try_from(fd).unwrap(),
-    };
+    let mut ev = libc::epoll_event { events: EPOLL_IN_OUT_ET, u64: u64::try_from(fd).unwrap() };
     let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) };
     assert_ne!(res, -1);
 
@@ -428,13 +388,11 @@ 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();
-    let res: i32 = unsafe {
-        libc::write(newfd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
-    };
+    let res = unsafe { libc::write(newfd, sized_8_data.as_ptr() as *const libc::c_void, 8) };
     assert_eq!(res, 8);
 
     // Close the dupped fd.
@@ -442,7 +400,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
@@ -454,9 +412,7 @@ fn test_event_overwrite() {
 
     // Write to the eventfd instance.
     let sized_8_data: [u8; 8] = 1_u64.to_ne_bytes();
-    let res: i32 = unsafe {
-        libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8).try_into().unwrap()
-    };
+    let res = unsafe { libc::write(fd, sized_8_data.as_ptr() as *const libc::c_void, 8) };
     assert_eq!(res, 8);
 
     // Create an epoll instance.
@@ -464,11 +420,8 @@ fn test_event_overwrite() {
     assert_ne!(epfd, -1);
 
     // Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
-    // EPOLLET is negative number for i32 so casting is needed to do proper bitwise OR for u32.
-    let epollet = libc::EPOLLET as u32;
-    let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet;
     let mut ev = libc::epoll_event {
-        events: u32::try_from(flags).unwrap(),
+        events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _,
         u64: u64::try_from(fd).unwrap(),
     };
     let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fd, &mut ev) };
@@ -476,13 +429,13 @@ fn test_event_overwrite() {
 
     // Read from the eventfd instance.
     let mut buf: [u8; 8] = [0; 8];
-    let res: i32 = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), 8).try_into().unwrap() };
+    let res = unsafe { libc::read(fd, buf.as_mut_ptr().cast(), 8) };
     assert_eq!(res, 8);
 
     // 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.
@@ -498,18 +451,22 @@ fn test_socketpair_read() {
     assert_eq!(res, 0);
 
     // Register both fd to the same epoll instance.
-    let epollet = libc::EPOLLET as u32;
-    let flags = u32::try_from(libc::EPOLLIN | libc::EPOLLOUT).unwrap() | epollet;
-    let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: fds[0] as u64 };
-    let mut res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) };
+    let mut ev = libc::epoll_event {
+        events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _,
+        u64: fds[0] as u64,
+    };
+    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[0], &mut ev) };
     assert_ne!(res, -1);
-    let mut ev = libc::epoll_event { events: u32::try_from(flags).unwrap(), u64: fds[1] as u64 };
-    res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
+    let mut ev = libc::epoll_event {
+        events: (libc::EPOLLIN | libc::EPOLLOUT | libc::EPOLLET) as _,
+        u64: fds[1] as u64,
+    };
+    let res = unsafe { libc::epoll_ctl(epfd, libc::EPOLL_CTL_ADD, fds[1], &mut ev) };
     assert_ne!(res, -1);
 
     // Write 5 bytes to fds[1].
     let data = "abcde".as_bytes().as_ptr();
-    res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5).try_into().unwrap() };
+    let res = unsafe { libc::write(fds[1], data as *const libc::c_void, 5) };
     assert_eq!(res, 5);
 
     //Two notification should be received.
@@ -519,14 +476,12 @@ 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].
     let mut buf: [u8; 3] = [0; 3];
-    res = unsafe {
-        libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap()
-    };
+    let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) };
     assert_eq!(res, 3);
     assert_eq!(buf, "abc".as_bytes());
 
@@ -534,13 +489,11 @@ 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];
-    res = unsafe {
-        libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t).try_into().unwrap()
-    };
+    let res = unsafe { libc::read(fds[0], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) };
     assert_eq!(res, 2);
     assert_eq!(buf, "de".as_bytes());
 
@@ -548,5 +501,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)]));
 }