diff --git a/src/uu/seq/src/seq.rs b/src/uu/seq/src/seq.rs index 501b12ac0..493b0c589 100644 --- a/src/uu/seq/src/seq.rs +++ b/src/uu/seq/src/seq.rs @@ -12,7 +12,7 @@ use num_traits::One; use num_traits::Zero; use num_traits::{Num, ToPrimitive}; use std::cmp; -use std::io::{stdout, Write}; +use std::io::{stdout, ErrorKind, Write}; use std::str::FromStr; use uucore::display::Quotable; @@ -192,7 +192,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 { .num_digits() .max(increment.num_digits()) .max(last.num_digits()); - match (first, last, increment) { + let result = match (first, last, increment) { (Number::MinusZero, Number::BigInt(last), Number::BigInt(increment)) => print_seq_integers( (BigInt::zero(), increment, last), options.separator, @@ -219,8 +219,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 { options.widths, padding, ), + }; + match result { + Ok(_) => 0, + Err(err) if err.kind() == ErrorKind::BrokenPipe => 0, + Err(_) => 1, } - 0 } pub fn uu_app() -> App<'static, 'static> { @@ -276,7 +280,9 @@ fn print_seq( terminator: String, pad: bool, padding: usize, -) { +) -> std::io::Result<()> { + let stdout = stdout(); + let mut stdout = stdout.lock(); let (first, increment, last) = range; let mut i = 0isize; let mut value = first + i as f64 * increment; @@ -286,20 +292,21 @@ fn print_seq( let before_dec = istr.find('.').unwrap_or(ilen); if pad && before_dec < padding { for _ in 0..(padding - before_dec) { - print!("0"); + write!(stdout, "0")?; } } - print!("{}", istr); + write!(stdout, "{}", istr)?; i += 1; value = first + i as f64 * increment; if !done_printing(&value, &increment, &last) { - print!("{}", separator); + write!(stdout, "{}", separator)?; } } if (first >= last && increment < 0f64) || (first <= last && increment > 0f64) { - print!("{}", terminator); + write!(stdout, "{}", terminator)?; } - crash_if_err!(1, stdout().flush()); + stdout.flush()?; + Ok(()) } /// Print an integer sequence. @@ -323,31 +330,34 @@ fn print_seq_integers( pad: bool, padding: usize, is_first_minus_zero: bool, -) { +) -> std::io::Result<()> { + let stdout = stdout(); + let mut stdout = stdout.lock(); let (first, increment, last) = range; let mut value = first; let mut is_first_iteration = true; while !done_printing(&value, &increment, &last) { if !is_first_iteration { - print!("{}", separator); + write!(stdout, "{}", separator)?; } let mut width = padding; if is_first_iteration && is_first_minus_zero { - print!("-"); + write!(stdout, "-")?; width -= 1; } is_first_iteration = false; if pad { - print!("{number:>0width$}", number = value, width = width); + write!(stdout, "{number:>0width$}", number = value, width = width)?; } else { - print!("{}", value); + write!(stdout, "{}", value)?; } value += &increment; } if !is_first_iteration { - print!("{}", terminator); + write!(stdout, "{}", terminator)?; } + Ok(()) } #[cfg(test)] diff --git a/tests/by-util/test_seq.rs b/tests/by-util/test_seq.rs index 458769839..4325c7fba 100644 --- a/tests/by-util/test_seq.rs +++ b/tests/by-util/test_seq.rs @@ -1,4 +1,5 @@ use crate::common::util::*; +use std::io::Read; #[test] fn test_rejects_nan() { @@ -176,3 +177,26 @@ fn test_width_negative_zero() { .stdout_is("-0\n01\n") .no_stderr(); } + +// TODO This is duplicated from `test_yes.rs`; refactor them. +/// Run `seq`, capture some of the output, close the pipe, and verify it. +fn run(args: &[&str], expected: &[u8]) { + let mut cmd = new_ucmd!(); + let mut child = cmd.args(args).run_no_wait(); + let mut stdout = child.stdout.take().unwrap(); + let mut buf = vec![0; expected.len()]; + stdout.read_exact(&mut buf).unwrap(); + drop(stdout); + assert!(child.wait().unwrap().success()); + assert_eq!(buf.as_slice(), expected); +} + +#[test] +fn test_neg_inf() { + run(&["--", "-inf", "0"], b"-inf\n-inf\n-inf\n"); +} + +#[test] +fn test_inf() { + run(&["inf"], b"1\n2\n3\n"); +}