1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-30 20:47:46 +00:00

Merge pull request #5373 from cakebaker/head_add_some_empty_lines

head: add some empty lines
This commit is contained in:
Sylvestre Ledru 2023-10-07 16:32:41 +02:00 committed by GitHub
commit 77c120db2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 1 deletions

View file

@ -3,7 +3,7 @@
// For the full copyright and license information, please view the LICENSE // For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code. // file that was distributed with this source code.
// spell-checker:ignore (vars) zlines BUFWRITER seekable // spell-checker:ignore (vars) BUFWRITER seekable
use clap::{crate_version, Arg, ArgAction, ArgMatches, Command}; use clap::{crate_version, Arg, ArgAction, ArgMatches, Command};
use std::ffi::OsString; use std::ffi::OsString;
@ -31,6 +31,7 @@ mod options {
pub const FILES_NAME: &str = "FILE"; pub const FILES_NAME: &str = "FILE";
pub const PRESUME_INPUT_PIPE: &str = "-PRESUME-INPUT-PIPE"; pub const PRESUME_INPUT_PIPE: &str = "-PRESUME-INPUT-PIPE";
} }
mod parse; mod parse;
mod take; mod take;
use take::take_all_but; use take::take_all_but;
@ -519,6 +520,7 @@ mod tests {
use std::io::Cursor; use std::io::Cursor;
use super::*; use super::*;
fn options(args: &str) -> Result<HeadOptions, String> { fn options(args: &str) -> Result<HeadOptions, String> {
let combined = "head ".to_owned() + args; let combined = "head ".to_owned() + args;
let args = combined.split_whitespace().map(OsString::from); let args = combined.split_whitespace().map(OsString::from);
@ -526,6 +528,7 @@ mod tests {
.get_matches_from(arg_iterate(args).map_err(|_| String::from("Arg iterate failed"))?); .get_matches_from(arg_iterate(args).map_err(|_| String::from("Arg iterate failed"))?);
HeadOptions::get_from(&matches) HeadOptions::get_from(&matches)
} }
#[test] #[test]
fn test_args_modes() { fn test_args_modes() {
let args = options("-n -10M -vz").unwrap(); let args = options("-n -10M -vz").unwrap();
@ -533,6 +536,7 @@ mod tests {
assert!(args.verbose); assert!(args.verbose);
assert_eq!(args.mode, Mode::AllButLastLines(10 * 1024 * 1024)); assert_eq!(args.mode, Mode::AllButLastLines(10 * 1024 * 1024));
} }
#[test] #[test]
fn test_gnu_compatibility() { fn test_gnu_compatibility() {
let args = options("-n 1 -c 1 -n 5 -c kiB -vqvqv").unwrap(); // spell-checker:disable-line let args = options("-n 1 -c 1 -n 5 -c kiB -vqvqv").unwrap(); // spell-checker:disable-line
@ -542,6 +546,7 @@ mod tests {
assert_eq!(options("-2b").unwrap().mode, Mode::FirstBytes(1024)); assert_eq!(options("-2b").unwrap().mode, Mode::FirstBytes(1024));
assert_eq!(options("-5 -c 1").unwrap().mode, Mode::FirstBytes(1)); assert_eq!(options("-5 -c 1").unwrap().mode, Mode::FirstBytes(1));
} }
#[test] #[test]
fn all_args_test() { fn all_args_test() {
assert!(options("--silent").unwrap().quiet); assert!(options("--silent").unwrap().quiet);
@ -559,11 +564,13 @@ mod tests {
assert_eq!(options("--bytes 15").unwrap().mode, Mode::FirstBytes(15)); assert_eq!(options("--bytes 15").unwrap().mode, Mode::FirstBytes(15));
assert_eq!(options("-c 15").unwrap().mode, Mode::FirstBytes(15)); assert_eq!(options("-c 15").unwrap().mode, Mode::FirstBytes(15));
} }
#[test] #[test]
fn test_options_errors() { fn test_options_errors() {
assert!(options("-n IsThisTheRealLife?").is_err()); assert!(options("-n IsThisTheRealLife?").is_err());
assert!(options("-c IsThisJustFantasy").is_err()); assert!(options("-c IsThisJustFantasy").is_err());
} }
#[test] #[test]
fn test_options_correct_defaults() { fn test_options_correct_defaults() {
let opts = HeadOptions::default(); let opts = HeadOptions::default();
@ -574,6 +581,7 @@ mod tests {
assert_eq!(opts.mode, Mode::FirstLines(10)); assert_eq!(opts.mode, Mode::FirstLines(10));
assert!(opts.files.is_empty()); assert!(opts.files.is_empty());
} }
fn arg_outputs(src: &str) -> Result<String, ()> { fn arg_outputs(src: &str) -> Result<String, ()> {
let split = src.split_whitespace().map(OsString::from); let split = src.split_whitespace().map(OsString::from);
match arg_iterate(split) { match arg_iterate(split) {
@ -586,6 +594,7 @@ mod tests {
Err(_) => Err(()), Err(_) => Err(()),
} }
} }
#[test] #[test]
fn test_arg_iterate() { fn test_arg_iterate() {
// test that normal args remain unchanged // test that normal args remain unchanged
@ -610,6 +619,7 @@ mod tests {
//test that empty args remain unchanged //test that empty args remain unchanged
assert_eq!(arg_outputs("head"), Ok("head".to_owned())); assert_eq!(arg_outputs("head"), Ok("head".to_owned()));
} }
#[test] #[test]
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
fn test_arg_iterate_bad_encoding() { fn test_arg_iterate_bad_encoding() {
@ -618,6 +628,7 @@ mod tests {
// this arises from a conversion from OsString to &str // this arises from a conversion from OsString to &str
assert!(arg_iterate(vec![OsString::from("head"), invalid].into_iter()).is_err()); assert!(arg_iterate(vec![OsString::from("head"), invalid].into_iter()).is_err());
} }
#[test] #[test]
fn read_early_exit() { fn read_early_exit() {
let mut empty = std::io::BufReader::new(std::io::Cursor::new(Vec::new())); let mut empty = std::io::BufReader::new(std::io::Cursor::new(Vec::new()));

View file

@ -11,6 +11,7 @@ pub enum ParseError {
Syntax, Syntax,
Overflow, Overflow,
} }
/// Parses obsolete syntax /// Parses obsolete syntax
/// head -NUM\[kmzv\] // spell-checker:disable-line /// head -NUM\[kmzv\] // spell-checker:disable-line
pub fn parse_obsolete(src: &str) -> Option<Result<impl Iterator<Item = OsString>, ParseError>> { pub fn parse_obsolete(src: &str) -> Option<Result<impl Iterator<Item = OsString>, ParseError>> {
@ -135,6 +136,7 @@ pub fn parse_num(src: &str) -> Result<(u64, bool), ParseSizeError> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
fn obsolete(src: &str) -> Option<Result<Vec<String>, ParseError>> { fn obsolete(src: &str) -> Option<Result<Vec<String>, ParseError>> {
let r = parse_obsolete(src); let r = parse_obsolete(src);
match r { match r {
@ -145,9 +147,11 @@ mod tests {
None => None, None => None,
} }
} }
fn obsolete_result(src: &[&str]) -> Option<Result<Vec<String>, ParseError>> { fn obsolete_result(src: &[&str]) -> Option<Result<Vec<String>, ParseError>> {
Some(Ok(src.iter().map(|s| s.to_string()).collect())) Some(Ok(src.iter().map(|s| s.to_string()).collect()))
} }
#[test] #[test]
fn test_parse_numbers_obsolete() { fn test_parse_numbers_obsolete() {
assert_eq!(obsolete("-5"), obsolete_result(&["-n", "5"])); assert_eq!(obsolete("-5"), obsolete_result(&["-n", "5"]));
@ -167,16 +171,19 @@ mod tests {
obsolete_result(&["-z", "-c", "110100480"]) obsolete_result(&["-z", "-c", "110100480"])
); );
} }
#[test] #[test]
fn test_parse_errors_obsolete() { fn test_parse_errors_obsolete() {
assert_eq!(obsolete("-5n"), Some(Err(ParseError::Syntax))); assert_eq!(obsolete("-5n"), Some(Err(ParseError::Syntax)));
assert_eq!(obsolete("-5c5"), Some(Err(ParseError::Syntax))); assert_eq!(obsolete("-5c5"), Some(Err(ParseError::Syntax)));
} }
#[test] #[test]
fn test_parse_obsolete_no_match() { fn test_parse_obsolete_no_match() {
assert_eq!(obsolete("-k"), None); assert_eq!(obsolete("-k"), None);
assert_eq!(obsolete("asd"), None); assert_eq!(obsolete("asd"), None);
} }
#[test] #[test]
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
fn test_parse_obsolete_overflow_x64() { fn test_parse_obsolete_overflow_x64() {
@ -189,6 +196,7 @@ mod tests {
Some(Err(ParseError::Overflow)) Some(Err(ParseError::Overflow))
); );
} }
#[test] #[test]
#[cfg(target_pointer_width = "32")] #[cfg(target_pointer_width = "32")]
fn test_parse_obsolete_overflow_x32() { fn test_parse_obsolete_overflow_x32() {