1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

Merge pull request #861 from ProgVal/test-tail-f

tail: Add test for `tail -f`.
This commit is contained in:
Heather 2016-04-07 23:49:33 +04:00
commit 02779fd3d2
3 changed files with 63 additions and 25 deletions

View file

@ -33,7 +33,7 @@ BUILDDIR := $(BASEDIR)/target/${PROFILE}/
PKG_BUILDDIR := $(BUILDDIR)/deps/ PKG_BUILDDIR := $(BUILDDIR)/deps/
BUSYBOX_ROOT := $(BASEDIR)/tmp/ BUSYBOX_ROOT := $(BASEDIR)/tmp/
BUSYBOX_VER := 1.24.1 BUSYBOX_VER := 1.22.0
BUSYBOX_SRC:=$(BUSYBOX_ROOT)/busybox-$(BUSYBOX_VER)/ BUSYBOX_SRC:=$(BUSYBOX_ROOT)/busybox-$(BUSYBOX_VER)/
# Possible programs # Possible programs

View file

@ -3,7 +3,7 @@
extern crate tempdir; extern crate tempdir;
use std::env; use std::env;
use std::fs::{self, File}; use std::fs::{self, File, OpenOptions};
use std::io::{Read, Write, Result}; use std::io::{Read, Write, Result};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
#[cfg(unix)] #[cfg(unix)]
@ -11,11 +11,13 @@ use std::os::unix::fs::symlink as symlink_file;
#[cfg(windows)] #[cfg(windows)]
use std::os::windows::fs::symlink_file; use std::os::windows::fs::symlink_file;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio, Child};
use std::str::from_utf8; use std::str::from_utf8;
use std::ffi::OsStr; use std::ffi::OsStr;
use self::tempdir::TempDir; use self::tempdir::TempDir;
use std::rc::Rc; use std::rc::Rc;
use std::thread::sleep;
use std::time::Duration;
#[cfg(windows)] #[cfg(windows)]
static PROGNAME: &'static str = "target\\debug\\uutils.exe"; static PROGNAME: &'static str = "target\\debug\\uutils.exe";
@ -242,6 +244,12 @@ impl AtPath {
let _ = f.write(contents.as_bytes()); let _ = f.write(contents.as_bytes());
} }
pub fn append(&self, name: &str, contents: &str) {
log_info("open(append)", self.plus_as_string(name));
let mut f = OpenOptions::new().write(true).append(true).open(self.plus(name)).unwrap();
let _ = f.write(contents.as_bytes());
}
pub fn mkdir(&self, dir: &str) { pub fn mkdir(&self, dir: &str) {
log_info("mkdir", self.plus_as_string(dir)); log_info("mkdir", self.plus_as_string(dir));
fs::create_dir(&self.plus(dir)).unwrap(); fs::create_dir(&self.plus(dir)).unwrap();
@ -480,35 +488,38 @@ impl UCommand {
Box::new(self) Box::new(self)
} }
pub fn run(&mut self) -> CmdResult { /// Spawns the command, feeds the stdin if any, and returns immediately.
pub fn run_no_wait(&mut self) -> Child {
if self.has_run { if self.has_run {
panic!(ALREADY_RUN); panic!(ALREADY_RUN);
} }
self.has_run = true; self.has_run = true;
log_info("run", &self.comm_string); log_info("run", &self.comm_string);
let prog = match self.stdin { let mut result = self.raw
Some(ref input) => { .stdin(Stdio::piped())
let mut result = self.raw .stdout(Stdio::piped())
.stdin(Stdio::piped()) .stderr(Stdio::piped())
.stdout(Stdio::piped()) .spawn()
.stderr(Stdio::piped()) .unwrap();
.spawn()
.unwrap();
result.stdin if let Some(ref input) = self.stdin {
.take() result.stdin
.unwrap_or_else( .take()
|| panic!( .unwrap_or_else(
"Could not take child process stdin")) || panic!(
.write_all(&input) "Could not take child process stdin"))
.unwrap_or_else(|e| panic!("{}", e)); .write_all(&input)
.unwrap_or_else(|e| panic!("{}", e));
}
result
}
/// Spawns the command, feeds the stdin if any, waits for the result
/// and returns it.
pub fn run(&mut self) -> CmdResult {
let prog = self.run_no_wait().wait_with_output().unwrap();
result.wait_with_output().unwrap()
}
None => {
self.raw.output().unwrap()
}
};
CmdResult { CmdResult {
success: prog.status.success(), success: prog.status.success(),
stdout: from_utf8(&prog.stdout).unwrap().to_string(), stdout: from_utf8(&prog.stdout).unwrap().to_string(),
@ -541,6 +552,14 @@ impl UCommand {
} }
} }
pub fn read_size(child: &mut Child, size: usize) -> String {
let mut output = Vec::new();
output.resize(size, 0);
sleep(Duration::from_millis(100));
child.stdout.as_mut().unwrap().read(output.as_mut_slice()).unwrap();
String::from_utf8(output).unwrap()
}
// returns a testSet and a ucommand initialized to the utility binary // returns a testSet and a ucommand initialized to the utility binary
// operating in the fixtures directory with a cleared environment // operating in the fixtures directory with a cleared environment
pub fn testset_and_ucommand(utilname: &str) -> (TestSet, UCommand) { pub fn testset_and_ucommand(utilname: &str) -> (TestSet, UCommand) {

View file

@ -1,6 +1,7 @@
extern crate uu_tail; extern crate uu_tail;
use uu_tail::parse_size; use uu_tail::parse_size;
use std::io::Read;
use std::io::Write; use std::io::Write;
#[macro_use] #[macro_use]
@ -41,6 +42,24 @@ fn test_null_default() {
assert_eq!(result.stdout, at.read("foobar_with_null_default.expected")); assert_eq!(result.stdout, at.read("foobar_with_null_default.expected"));
} }
#[test]
fn test_follow() {
let (at, mut ucmd) = testing(UTIL_NAME);
let mut child = ucmd.arg("-f").arg(FOOBAR_TXT).run_no_wait();
let expected = at.read("foobar_single_default.expected");
assert_eq!(read_size(&mut child, expected.len()), expected);
// We write in a temporary copy of foobar.txt
let expected = "line1\nline2\n";
at.append(FOOBAR_TXT, expected);
assert_eq!(read_size(&mut child, expected.len()), expected);
child.kill().unwrap();
}
#[test] #[test]
fn test_single_big_args() { fn test_single_big_args() {
const FILE: &'static str = "single_big_args.txt"; const FILE: &'static str = "single_big_args.txt";