2020-05-04 06:25:36 +00:00
extern crate tail ;
2015-12-12 21:24:48 +00:00
2020-05-04 06:25:36 +00:00
use self ::tail ::parse_size ;
2020-05-25 17:05:26 +00:00
use crate ::common ::util ::* ;
2016-05-22 07:46:54 +00:00
use std ::char ::from_digit ;
2016-12-20 01:47:40 +00:00
use std ::io ::Write ;
2015-12-12 21:24:48 +00:00
2016-03-27 21:41:56 +00:00
static FOOBAR_TXT : & 'static str = " foobar.txt " ;
2016-05-30 20:34:53 +00:00
static FOOBAR_2_TXT : & 'static str = " foobar2.txt " ;
2016-04-02 10:32:33 +00:00
static FOOBAR_WITH_NULL_TXT : & 'static str = " foobar_with_null.txt " ;
2015-12-12 21:24:48 +00:00
#[ test ]
fn test_stdin_default ( ) {
2020-04-13 18:36:03 +00:00
new_ucmd! ( )
. pipe_in_fixture ( FOOBAR_TXT )
. run ( )
. stdout_is_fixture ( " foobar_stdin_default.expected " ) ;
2015-12-12 21:24:48 +00:00
}
#[ test ]
fn test_single_default ( ) {
2020-04-13 18:36:03 +00:00
new_ucmd! ( )
. arg ( FOOBAR_TXT )
. run ( )
. stdout_is_fixture ( " foobar_single_default.expected " ) ;
2015-12-12 21:24:48 +00:00
}
2016-03-20 05:25:53 +00:00
2016-03-27 21:42:45 +00:00
#[ test ]
fn test_n_greater_than_number_of_lines ( ) {
2020-04-13 18:36:03 +00:00
new_ucmd! ( )
. arg ( " -n " )
. arg ( " 99999999 " )
. arg ( FOOBAR_TXT )
. run ( )
2016-07-29 21:26:32 +00:00
. stdout_is_fixture ( FOOBAR_TXT ) ;
2016-03-27 21:42:45 +00:00
}
2016-04-02 10:32:33 +00:00
#[ test ]
fn test_null_default ( ) {
2020-04-13 18:36:03 +00:00
new_ucmd! ( )
. arg ( " -z " )
. arg ( FOOBAR_WITH_NULL_TXT )
. run ( )
. stdout_is_fixture ( " foobar_with_null_default.expected " ) ;
2016-04-02 10:32:33 +00:00
}
2016-04-02 21:09:20 +00:00
#[ test ]
fn test_follow ( ) {
2016-08-23 11:52:43 +00:00
let ( at , mut ucmd ) = at_and_ucmd! ( ) ;
2016-04-02 21:09:20 +00:00
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 \n line2 \n " ;
at . append ( FOOBAR_TXT , expected ) ;
assert_eq! ( read_size ( & mut child , expected . len ( ) ) , expected ) ;
child . kill ( ) . unwrap ( ) ;
}
2016-05-30 20:34:53 +00:00
#[ test ]
fn test_follow_multiple ( ) {
2016-08-23 11:52:43 +00:00
let ( at , mut ucmd ) = at_and_ucmd! ( ) ;
2020-04-13 18:36:03 +00:00
let mut child = ucmd
. arg ( " -f " )
. arg ( FOOBAR_TXT )
. arg ( FOOBAR_2_TXT )
. run_no_wait ( ) ;
2016-05-30 20:34:53 +00:00
let expected = at . read ( " foobar_follow_multiple.expected " ) ;
assert_eq! ( read_size ( & mut child , expected . len ( ) ) , expected ) ;
let first_append = " trois \n " ;
at . append ( FOOBAR_2_TXT , first_append ) ;
assert_eq! ( read_size ( & mut child , first_append . len ( ) ) , first_append ) ;
let second_append = " doce \n trece \n " ;
let expected = at . read ( " foobar_follow_multiple_appended.expected " ) ;
at . append ( FOOBAR_TXT , second_append ) ;
assert_eq! ( read_size ( & mut child , expected . len ( ) ) , expected ) ;
child . kill ( ) . unwrap ( ) ;
}
2016-05-31 20:40:06 +00:00
#[ test ]
fn test_follow_stdin ( ) {
2020-04-13 18:36:03 +00:00
new_ucmd! ( )
. arg ( " -f " )
. pipe_in_fixture ( FOOBAR_TXT )
. run ( )
. stdout_is_fixture ( " follow_stdin.expected " ) ;
2016-05-31 20:40:06 +00:00
}
2021-02-23 09:25:06 +00:00
// FixME: test PASSES for usual windows builds, but fails for coverage testing builds (likely related to the specific RUSTFLAGS '-Zpanic_abort_tests -Cpanic=abort') This test also breaks tty settings under bash requiring a 'stty sane' or reset.
#[ cfg(disable_until_fixed) ]
2016-12-20 01:47:40 +00:00
#[ test ]
fn test_follow_with_pid ( ) {
2020-08-10 05:15:26 +00:00
use std ::process ::{ Command , Stdio } ;
use std ::thread ::sleep ;
use std ::time ::Duration ;
2016-12-20 01:47:40 +00:00
let ( at , mut ucmd ) = at_and_ucmd! ( ) ;
#[ cfg(unix) ]
let dummy_cmd = " sh " ;
#[ cfg(windows) ]
let dummy_cmd = " cmd " ;
2020-04-13 18:36:03 +00:00
let mut dummy = Command ::new ( dummy_cmd )
. stdout ( Stdio ::null ( ) )
. spawn ( )
. unwrap ( ) ;
2016-12-20 01:47:40 +00:00
let pid = dummy . id ( ) ;
2020-04-13 18:36:03 +00:00
let mut child = ucmd
. arg ( " -f " )
. arg ( format! ( " --pid= {} " , pid ) )
. arg ( FOOBAR_TXT )
. arg ( FOOBAR_2_TXT )
. run_no_wait ( ) ;
2016-12-20 01:47:40 +00:00
let expected = at . read ( " foobar_follow_multiple.expected " ) ;
assert_eq! ( read_size ( & mut child , expected . len ( ) ) , expected ) ;
let first_append = " trois \n " ;
at . append ( FOOBAR_2_TXT , first_append ) ;
assert_eq! ( read_size ( & mut child , first_append . len ( ) ) , first_append ) ;
let second_append = " doce \n trece \n " ;
let expected = at . read ( " foobar_follow_multiple_appended.expected " ) ;
at . append ( FOOBAR_TXT , second_append ) ;
assert_eq! ( read_size ( & mut child , expected . len ( ) ) , expected ) ;
// kill the dummy process and give tail time to notice this
dummy . kill ( ) . unwrap ( ) ;
let _ = dummy . wait ( ) ;
sleep ( Duration ::from_secs ( 1 ) ) ;
let third_append = " should \n be \n ignored \n " ;
at . append ( FOOBAR_TXT , third_append ) ;
assert_eq! ( read_size ( & mut child , 1 ) , " \u{0} " ) ;
// On Unix, trying to kill a process that's already dead is fine; on Windows it's an error.
#[ cfg(unix) ]
child . kill ( ) . unwrap ( ) ;
#[ cfg(windows) ]
assert_eq! ( child . kill ( ) . is_err ( ) , true ) ;
}
2016-03-26 19:36:15 +00:00
#[ test ]
fn test_single_big_args ( ) {
const FILE : & 'static str = " single_big_args.txt " ;
const EXPECTED_FILE : & 'static str = " single_big_args_expected.txt " ;
const LINES : usize = 1_000_000 ;
const N_ARG : usize = 100_000 ;
2016-03-20 05:25:53 +00:00
2016-08-23 11:52:43 +00:00
let ( at , mut ucmd ) = at_and_ucmd! ( ) ;
2016-03-20 05:25:53 +00:00
2016-05-22 19:29:23 +00:00
let mut big_input = at . make_file ( FILE ) ;
2016-03-26 19:36:15 +00:00
for i in 0 .. LINES {
write! ( & mut big_input , " Line {} \n " , i ) . expect ( " Could not write to FILE " ) ;
2016-03-20 05:25:53 +00:00
}
2016-03-26 19:36:15 +00:00
big_input . flush ( ) . expect ( " Could not flush FILE " ) ;
2016-03-20 05:25:53 +00:00
2016-05-22 19:29:23 +00:00
let mut big_expected = at . make_file ( EXPECTED_FILE ) ;
2016-03-26 19:36:15 +00:00
for i in ( LINES - N_ARG ) .. LINES {
write! ( & mut big_expected , " Line {} \n " , i ) . expect ( " Could not write to EXPECTED_FILE " ) ;
}
big_expected . flush ( ) . expect ( " Could not flush EXPECTED_FILE " ) ;
2016-03-20 05:25:53 +00:00
2020-04-13 18:36:03 +00:00
ucmd . arg ( FILE )
. arg ( " -n " )
. arg ( format! ( " {} " , N_ARG ) )
. run ( )
. stdout_is ( at . read ( EXPECTED_FILE ) ) ;
2016-03-20 05:25:53 +00:00
}
2016-03-26 18:52:10 +00:00
#[ test ]
fn test_bytes_single ( ) {
2020-04-13 18:36:03 +00:00
new_ucmd! ( )
. arg ( " -c " )
. arg ( " 10 " )
. arg ( FOOBAR_TXT )
. run ( )
2016-07-29 21:26:32 +00:00
. stdout_is_fixture ( " foobar_bytes_single.expected " ) ;
2016-03-26 18:52:10 +00:00
}
2016-03-26 18:56:00 +00:00
#[ test ]
fn test_bytes_stdin ( ) {
2020-04-13 18:36:03 +00:00
new_ucmd! ( )
. arg ( " -c " )
. arg ( " 13 " )
. pipe_in_fixture ( FOOBAR_TXT )
. run ( )
. stdout_is_fixture ( " foobar_bytes_stdin.expected " ) ;
2016-03-26 18:56:00 +00:00
}
2016-03-27 21:33:55 +00:00
#[ test ]
fn test_bytes_big ( ) {
const FILE : & 'static str = " test_bytes_big.txt " ;
const EXPECTED_FILE : & 'static str = " test_bytes_big_expected.txt " ;
const BYTES : usize = 1_000_000 ;
const N_ARG : usize = 100_000 ;
2016-08-23 11:52:43 +00:00
let ( at , mut ucmd ) = at_and_ucmd! ( ) ;
2016-03-27 21:33:55 +00:00
2016-05-22 19:29:23 +00:00
let mut big_input = at . make_file ( FILE ) ;
2016-03-27 21:33:55 +00:00
for i in 0 .. BYTES {
2016-05-22 07:46:54 +00:00
let digit = from_digit ( ( i % 10 ) as u32 , 10 ) . unwrap ( ) ;
2016-03-27 21:33:55 +00:00
write! ( & mut big_input , " {} " , digit ) . expect ( " Could not write to FILE " ) ;
}
big_input . flush ( ) . expect ( " Could not flush FILE " ) ;
2016-05-22 19:29:23 +00:00
let mut big_expected = at . make_file ( EXPECTED_FILE ) ;
2016-03-27 21:33:55 +00:00
for i in ( BYTES - N_ARG ) .. BYTES {
2016-05-22 07:46:54 +00:00
let digit = from_digit ( ( i % 10 ) as u32 , 10 ) . unwrap ( ) ;
2016-03-27 21:33:55 +00:00
write! ( & mut big_expected , " {} " , digit ) . expect ( " Could not write to EXPECTED_FILE " ) ;
}
big_expected . flush ( ) . expect ( " Could not flush EXPECTED_FILE " ) ;
2020-04-13 18:36:03 +00:00
let result = ucmd
. arg ( FILE )
. arg ( " -c " )
. arg ( format! ( " {} " , N_ARG ) )
2021-04-17 12:22:20 +00:00
. succeeds ( )
. stdout_move_str ( ) ;
2016-03-27 21:33:55 +00:00
let expected = at . read ( EXPECTED_FILE ) ;
assert_eq! ( result . len ( ) , expected . len ( ) ) ;
for ( actual_char , expected_char ) in result . chars ( ) . zip ( expected . chars ( ) ) {
assert_eq! ( actual_char , expected_char ) ;
}
}
2016-04-02 21:16:11 +00:00
#[ test ]
fn test_parse_size ( ) {
// No suffix.
assert_eq! ( Ok ( 1234 ) , parse_size ( " 1234 " ) ) ;
// kB is 1000
assert_eq! ( Ok ( 9 * 1000 ) , parse_size ( " 9kB " ) ) ;
// K is 1024
assert_eq! ( Ok ( 2 * 1024 ) , parse_size ( " 2K " ) ) ;
let suffixes = [
( 'M' , 2 u32 ) ,
( 'G' , 3 u32 ) ,
( 'T' , 4 u32 ) ,
( 'P' , 5 u32 ) ,
( 'E' , 6 u32 ) ,
] ;
for & ( c , exp ) in & suffixes {
let s = format! ( " 2 {} B " , c ) ;
assert_eq! ( Ok ( 2 * ( 1000 as u64 ) . pow ( exp ) ) , parse_size ( & s ) ) ;
let s = format! ( " 2 {} " , c ) ;
assert_eq! ( Ok ( 2 * ( 1024 as u64 ) . pow ( exp ) ) , parse_size ( & s ) ) ;
}
// Sizes that are too big.
assert! ( parse_size ( " 1Z " ) . is_err ( ) ) ;
assert! ( parse_size ( " 1Y " ) . is_err ( ) ) ;
// Bad number
assert! ( parse_size ( " 328hdsf3290 " ) . is_err ( ) ) ;
}
#[ test ]
fn test_lines_with_size_suffix ( ) {
const FILE : & 'static str = " test_lines_with_size_suffix.txt " ;
const EXPECTED_FILE : & 'static str = " test_lines_with_size_suffix_expected.txt " ;
const LINES : usize = 3_000 ;
const N_ARG : usize = 2 * 1024 ;
2016-08-23 11:52:43 +00:00
let ( at , mut ucmd ) = at_and_ucmd! ( ) ;
2016-04-02 21:16:11 +00:00
2016-05-22 19:29:23 +00:00
let mut big_input = at . make_file ( FILE ) ;
2016-04-02 21:16:11 +00:00
for i in 0 .. LINES {
writeln! ( & mut big_input , " Line {} " , i ) . expect ( " Could not write to FILE " ) ;
}
big_input . flush ( ) . expect ( " Could not flush FILE " ) ;
2016-05-22 19:29:23 +00:00
let mut big_expected = at . make_file ( EXPECTED_FILE ) ;
2016-04-02 21:16:11 +00:00
for i in ( LINES - N_ARG ) .. LINES {
writeln! ( & mut big_expected , " Line {} " , i ) . expect ( " Could not write to EXPECTED_FILE " ) ;
}
big_expected . flush ( ) . expect ( " Could not flush EXPECTED_FILE " ) ;
2020-04-13 18:36:03 +00:00
ucmd . arg ( FILE )
. arg ( " -n " )
. arg ( " 2K " )
. run ( )
. stdout_is_fixture ( EXPECTED_FILE ) ;
2016-04-02 21:16:11 +00:00
}
2017-10-05 19:25:21 +00:00
#[ test ]
fn test_multiple_input_files ( ) {
2020-04-13 18:36:03 +00:00
new_ucmd! ( )
. arg ( FOOBAR_TXT )
. arg ( FOOBAR_2_TXT )
. run ( )
. stdout_is_fixture ( " foobar_follow_multiple.expected " ) ;
2017-10-05 19:25:21 +00:00
}
#[ test ]
fn test_multiple_input_files_with_suppressed_headers ( ) {
2020-04-13 18:36:03 +00:00
new_ucmd! ( )
. arg ( FOOBAR_TXT )
. arg ( FOOBAR_2_TXT )
. arg ( " -q " )
. run ( )
. stdout_is_fixture ( " foobar_multiple_quiet.expected " ) ;
2017-10-05 19:25:21 +00:00
}
#[ test ]
fn test_multiple_input_quiet_flag_overrides_verbose_flag_for_suppressing_headers ( ) {
// TODO: actually the later one should win, i.e. -qv should lead to headers being printed, -vq to them being suppressed
2020-04-13 18:36:03 +00:00
new_ucmd! ( )
. arg ( FOOBAR_TXT )
. arg ( FOOBAR_2_TXT )
. arg ( " -q " )
. arg ( " -v " )
. run ( )
. stdout_is_fixture ( " foobar_multiple_quiet.expected " ) ;
2017-10-05 19:25:21 +00:00
}
2021-03-22 09:01:54 +00:00
#[ test ]
fn test_negative_indexing ( ) {
let positive_lines_index = new_ucmd! ( ) . arg ( " -n " ) . arg ( " 5 " ) . arg ( FOOBAR_TXT ) . run ( ) ;
let negative_lines_index = new_ucmd! ( ) . arg ( " -n " ) . arg ( " -5 " ) . arg ( FOOBAR_TXT ) . run ( ) ;
let positive_bytes_index = new_ucmd! ( ) . arg ( " -c " ) . arg ( " 20 " ) . arg ( FOOBAR_TXT ) . run ( ) ;
let negative_bytes_index = new_ucmd! ( ) . arg ( " -c " ) . arg ( " -20 " ) . arg ( FOOBAR_TXT ) . run ( ) ;
2021-04-17 12:22:20 +00:00
assert_eq! ( positive_lines_index . stdout ( ) , negative_lines_index . stdout ( ) ) ;
assert_eq! ( positive_bytes_index . stdout ( ) , negative_bytes_index . stdout ( ) ) ;
2021-03-22 09:01:54 +00:00
}