From 5e2b582662b1c0ab28460629a846e9fe693120c5 Mon Sep 17 00:00:00 2001 From: Zhouyu Qian Date: Thu, 19 Apr 2018 18:02:30 -0700 Subject: Implement Debug trait for PollFd This is useful when using printf-style debugging to observe the variables of the program. Also includes a test. Fixes #885. --- src/poll.rs | 19 ++++++++++++++++++- test/test_poll.rs | 20 +++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/poll.rs b/src/poll.rs index f3046ff3..eb6b2417 100644 --- a/src/poll.rs +++ b/src/poll.rs @@ -4,6 +4,7 @@ use sys::time::TimeSpec; #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))] use sys::signal::SigSet; use std::os::unix::io::RawFd; +use std::fmt; use libc; use Result; @@ -19,7 +20,6 @@ use errno::Errno; /// retrieved by calling [`revents()`](#method.revents) on the `PollFd`. #[repr(C)] #[derive(Clone, Copy)] -#[allow(missing_debug_implementations)] pub struct PollFd { pollfd: libc::pollfd, } @@ -43,6 +43,23 @@ impl PollFd { } } +impl fmt::Debug for PollFd { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let pfd = self.pollfd; + let mut ds = f.debug_struct("PollFd"); + ds.field("fd", &pfd.fd); + match EventFlags::from_bits(pfd.events) { + None => ds.field("events", &pfd.events), + Some(ef) => ds.field("events", &ef), + }; + match EventFlags::from_bits(pfd.revents) { + None => ds.field("revents", &pfd.revents), + Some(ef) => ds.field("revents", &ef), + }; + ds.finish() + } +} + libc_bitflags! { /// These flags define the different events that can be monitored by `poll` and `ppoll` pub struct EventFlags: libc::c_short { diff --git a/test/test_poll.rs b/test/test_poll.rs index c28c8fd8..a9831ed4 100644 --- a/test/test_poll.rs +++ b/test/test_poll.rs @@ -1,7 +1,7 @@ use nix::poll::{EventFlags, poll, PollFd}; use nix::sys::signal::SigSet; use nix::sys::time::{TimeSpec, TimeValLike}; -use nix::unistd::{write, pipe}; +use nix::unistd::{write, pipe, close}; #[test] fn test_poll() { @@ -21,6 +21,24 @@ fn test_poll() { assert!(fds[0].revents().unwrap().contains(EventFlags::POLLIN)); } +#[test] +fn test_poll_debug() { + assert_eq!(format!("{:?}", PollFd::new(0, EventFlags::empty())), + "PollFd { fd: 0, events: (empty), revents: (empty) }"); + assert_eq!(format!("{:?}", PollFd::new(1, EventFlags::POLLIN)), + "PollFd { fd: 1, events: POLLIN, revents: (empty) }"); + + // Testing revents requires doing some I/O + let (r, w) = pipe().unwrap(); + let mut fds = [PollFd::new(r, EventFlags::POLLIN)]; + write(w, b" ").unwrap(); + close(w).unwrap(); + poll(&mut fds, -1).unwrap(); + assert_eq!(format!("{:?}", fds[0]), + format!("PollFd {{ fd: {}, events: POLLIN, revents: POLLIN | POLLHUP }}", r)); + close(r).unwrap(); +} + // ppoll(2) is the same as poll except for how it handles timeouts and signals. // Repeating the test for poll(2) should be sufficient to check that our // bindings are correct. -- cgit v1.2.3