Skip to content

Commit

Permalink
Add tracing and instrument functions to code and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lpenz committed Jul 30, 2023
1 parent 69e4d6f commit 1d74b4a
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 17 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Expand Up @@ -15,7 +15,11 @@ keywords = ["io", "non-blocking"]
[dependencies]
libc = "0.2.147"
memchr = "2.5.0"
tracing = "0.1.37"

[dev-dependencies]
color-eyre = "0.6.2"
polling = "2.8.0"
env_logger = "0.10.0"
test-log = { version = "0.2.12", features = ["trace"] }
tracing-subscriber = {version = "0.3", default-features = false, features = ["env-filter", "fmt"]}
5 changes: 4 additions & 1 deletion src/blocking.rs
Expand Up @@ -3,9 +3,11 @@
// file 'LICENSE', which is part of this source code package.

use libc::{F_GETFL, F_SETFL, O_NONBLOCK};
use std::fmt::Debug;
use std::io;
use std::os::fd::AsRawFd;

#[tracing::instrument]
fn fcntl(
fd: std::os::fd::RawFd,
cmd: libc::c_int,
Expand All @@ -18,7 +20,8 @@ fn fcntl(
Ok(result)
}

pub fn disable<R: AsRawFd>(reader: R) -> Result<(), io::Error> {
#[tracing::instrument]
pub fn disable<R: AsRawFd + Debug>(reader: R) -> Result<(), io::Error> {
let fd = reader.as_raw_fd();
let flags = fcntl(fd, F_GETFL, 0)?;
fcntl(fd, F_SETFL, flags | O_NONBLOCK)?;
Expand Down
16 changes: 12 additions & 4 deletions src/linereader.rs
Expand Up @@ -4,6 +4,7 @@

//! This module has the main type of this crate: [`LineReader`].

use std::fmt::Debug;
use std::io::{self, Read};
use std::os::fd::AsRawFd;
use std::{mem, str};
Expand All @@ -23,16 +24,18 @@ pub struct LineReader<R> {
lines: Vec<String>,
}

#[tracing::instrument(skip(buf))]
fn u8array_to_string(buf: &[u8]) -> Result<String, io::Error> {
match str::from_utf8(buf) {
Ok(line) => Ok(line.to_string()),
Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)),
}
}

impl<R: Read + AsRawFd> LineReader<R> {
impl<R: Read + AsRawFd + Debug> LineReader<R> {
/// Creates a new LineReader, setting the underlying
/// descriptor as non-blocking.
#[tracing::instrument]
pub fn new(reader: R) -> Result<Self, io::Error> {
let fd = reader.as_raw_fd();
blocking::disable(fd)?;
Expand All @@ -46,11 +49,12 @@ impl<R: Read + AsRawFd> LineReader<R> {
}
}

impl<R: Read> LineReader<R> {
impl<R: Read + Debug> LineReader<R> {
/// Creates a new LineReader.
///
/// Assumes the reader is already non-blocking, not configuring
/// anything in the underlying descriptor.
#[tracing::instrument]
pub fn from_nonblocking(reader: R) -> Result<Self, io::Error> {
Ok(Self {
reader,
Expand All @@ -61,6 +65,7 @@ impl<R: Read> LineReader<R> {
})
}

#[tracing::instrument(skip(self),fields(self.at_eof = %self.at_eof, self.num_lines=self.lines.len()))]
fn eval_buf(&mut self, mut pos: usize) -> Result<(), io::Error> {
loop {
if let Some(inewline) = memchr::memchr(b'\n', &self.buf[pos..self.used]) {
Expand All @@ -80,11 +85,13 @@ impl<R: Read> LineReader<R> {
}
}

impl<R: Read> LineRead for crate::LineReader<R> {
impl<R: Read + Debug> LineRead for crate::LineReader<R> {
#[tracing::instrument(skip(self),fields(self.at_eof = %self.at_eof, self.num_lines=self.lines.len()))]
fn eof(&self) -> bool {
self.at_eof
}

#[tracing::instrument(skip(self),fields(self.at_eof = %self.at_eof, self.num_lines=self.lines.len()))]
fn read_once(&mut self) -> Result<bool, io::Error> {
if self.at_eof {
return Ok(false);
Expand Down Expand Up @@ -123,6 +130,7 @@ impl<R: Read> LineRead for crate::LineReader<R> {
Ok(true)
}

#[tracing::instrument(skip(self),fields(self.at_eof = %self.at_eof, self.num_lines=self.lines.len()))]
fn lines_get(&mut self) -> Vec<String> {
mem::take(&mut self.lines)
}
Expand All @@ -134,4 +142,4 @@ impl<R: AsRawFd> AsRawFd for LineReader<R> {
}
}

impl<R: AsRawFd + Read> LineReadFd for LineReader<R> {}
impl<R: AsRawFd + Read + Debug> LineReadFd for LineReader<R> {}
25 changes: 13 additions & 12 deletions tests/lineriver_tests.rs
Expand Up @@ -15,6 +15,7 @@ use ::lineriver::*;
const SPARKLE_HEART: [u8; 4] = [240, 159, 146, 150];
const INVALID_UTF8: [u8; 4] = [0, 159, 146, 150];

#[tracing::instrument(skip(input))]
fn reader_for(input: &[u8]) -> Result<LineReader<UnixStream>> {
let (mut wr, rd) = std::os::unix::net::UnixStream::pair()?;
let reader = LineReader::new(rd)?;
Expand All @@ -23,15 +24,15 @@ fn reader_for(input: &[u8]) -> Result<LineReader<UnixStream>> {
Ok(reader)
}

#[test]
#[test_log::test]
fn test_oneline_newline() -> Result<()> {
let mut reader = reader_for(b"test\n")?;
reader.read_once()?;
assert_eq!(reader.lines_get(), vec!["test\n"]);
Ok(())
}

#[test]
#[test_log::test]
fn test_oneline_nonewline() -> Result<()> {
let mut reader = reader_for(b"test")?;
// First read_once gets the string.
Expand All @@ -42,7 +43,7 @@ fn test_oneline_nonewline() -> Result<()> {
Ok(())
}

#[test]
#[test_log::test]
fn test_twoline() -> Result<()> {
let mut reader = reader_for(b"1\n2\n")?;
// First read_once gets the string.
Expand All @@ -55,7 +56,7 @@ fn test_twoline() -> Result<()> {
Ok(())
}

#[test]
#[test_log::test]
fn test_threeline() -> Result<()> {
let mut reader = reader_for(b"1\n\n3\n")?;
// We only need one read_available to find eof
Expand All @@ -64,23 +65,23 @@ fn test_threeline() -> Result<()> {
Ok(())
}

#[test]
#[test_log::test]
fn test_empty() -> Result<()> {
let mut reader = reader_for(b"")?;
reader.read_once()?;
assert!(reader.lines_get().is_empty());
Ok(())
}

#[test]
#[test_log::test]
fn test_empty_line() -> Result<()> {
let mut reader = reader_for(b"\n")?;
reader.read_once()?;
assert_eq!(reader.lines_get(), vec!["\n"]);
Ok(())
}

#[test]
#[test_log::test]
fn test_read_past_end() -> Result<()> {
let mut reader = reader_for(b"")?;
for _ in 0..10 {
Expand All @@ -91,7 +92,7 @@ fn test_read_past_end() -> Result<()> {
Ok(())
}

#[test]
#[test_log::test]
fn test_utf8() -> Result<()> {
let heart = format!("\n{}\n\n", std::str::from_utf8(&SPARKLE_HEART)?);
let mut reader = reader_for(heart.as_bytes())?;
Expand All @@ -107,7 +108,7 @@ fn test_utf8() -> Result<()> {
Ok(())
}

#[test]
#[test_log::test]
fn test_invalid_utf8() -> Result<()> {
let mut invalid = Vec::from(INVALID_UTF8);
invalid.push(b'\n');
Expand All @@ -119,7 +120,7 @@ fn test_invalid_utf8() -> Result<()> {
Ok(())
}

#[test]
#[test_log::test]
fn test_addlines() -> Result<()> {
let (mut wr, rd) = std::os::unix::net::UnixStream::pair()?;
let mut reader = LineReader::new(rd)?;
Expand All @@ -143,15 +144,15 @@ fn test_addlines() -> Result<()> {
Ok(())
}

#[test]
#[test_log::test]
fn test_trat_reader() -> Result<()> {
let array = "abcdefgh".as_bytes();
let linereader = LineReader::from_nonblocking(array)?;
let _traitobj = &linereader as &dyn LineRead;
Ok(())
}

#[test]
#[test_log::test]
fn test_trat_readerfd() -> Result<()> {
let mut child = Command::new("true")
.stdout(Stdio::piped())
Expand Down

0 comments on commit 1d74b4a

Please sign in to comment.