mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-02 14:07:46 +00:00
Merge branch 'master' of github.com:uutils/coreutils into hbina-tr-reimplement-expansion
Signed-off-by: Hanif Bin Ariffin <hanif.ariffin.4326@gmail.com>
This commit is contained in:
commit
c4de592e90
34 changed files with 227 additions and 154 deletions
|
@ -6,9 +6,6 @@
|
|||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use platform_info::*;
|
||||
|
||||
use clap::{crate_version, App};
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
// For the full copyright and license information, please view the LICENSE file
|
||||
// that was distributed with this source code.
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::io::{stdin, Read};
|
||||
|
||||
use clap::App;
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
// For the full copyright and license information, please view the LICENSE file
|
||||
// that was distributed with this source code.
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use uu_base32::base_common;
|
||||
pub use uu_base32::uu_app;
|
||||
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
|
||||
//spell-checker:ignore (args) lsbf msbf
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{App, Arg};
|
||||
use uu_base32::base_common::{self, Config, BASE_CMD_PARSE_ERROR};
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
|
||||
#[cfg(unix)]
|
||||
extern crate unix_socket;
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
// last synced with: cat (GNU coreutils) 8.13
|
||||
use clap::{crate_version, App, Arg};
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
// spell-checker:ignore (ToDO) COMFOLLOW Chowner RFILE RFILE's derefer dgid nonblank nonprint nonprinting
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
use uucore::display::Quotable;
|
||||
pub use uucore::entries;
|
||||
use uucore::error::{FromIo, UResult, USimpleError};
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
// spell-checker:ignore (ToDO) COMFOLLOW Passwd RFILE RFILE's derefer dgid duid groupname
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
use uucore::display::Quotable;
|
||||
pub use uucore::entries::{self, Group, Locate, Passwd};
|
||||
use uucore::perms::{chown_base, options, IfFrom};
|
||||
|
|
|
@ -67,7 +67,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
// TODO: refactor the args and command matching
|
||||
// See: https://github.com/uutils/coreutils/pull/2365#discussion_r647849967
|
||||
let command: Vec<&str> = match commands.len() {
|
||||
1 => {
|
||||
0 => {
|
||||
let shell: &str = match user_shell {
|
||||
Err(_) => default_shell,
|
||||
Ok(ref s) => s.as_ref(),
|
||||
|
@ -77,12 +77,28 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
_ => commands,
|
||||
};
|
||||
|
||||
assert!(!command.is_empty());
|
||||
let chroot_command = command[0];
|
||||
let chroot_args = &command[1..];
|
||||
|
||||
// NOTE: Tests can only trigger code beyond this point if they're invoked with root permissions
|
||||
set_context(newroot, &matches);
|
||||
|
||||
let pstatus = Command::new(command[0])
|
||||
.args(&command[1..])
|
||||
let pstatus = Command::new(chroot_command)
|
||||
.args(chroot_args)
|
||||
.status()
|
||||
.unwrap_or_else(|e| crash!(1, "Cannot exec: {}", e));
|
||||
.unwrap_or_else(|e| {
|
||||
// TODO: Exit status:
|
||||
// 125 if chroot itself fails
|
||||
// 126 if command is found but cannot be invoked
|
||||
// 127 if command cannot be found
|
||||
crash!(
|
||||
1,
|
||||
"failed to run command {}: {}",
|
||||
command[0].to_string().quote(),
|
||||
e
|
||||
)
|
||||
});
|
||||
|
||||
if pstatus.success() {
|
||||
0
|
||||
|
|
|
@ -49,6 +49,7 @@ use std::path::{Path, PathBuf, StripPrefixError};
|
|||
use std::str::FromStr;
|
||||
use std::string::ToString;
|
||||
use uucore::backup_control::{self, BackupMode};
|
||||
use uucore::error::{set_exit_code, ExitCode, UError, UResult};
|
||||
use uucore::fs::{canonicalize, MissingHandling, ResolveMode};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
|
@ -105,6 +106,12 @@ quick_error! {
|
|||
}
|
||||
}
|
||||
|
||||
impl UError for Error {
|
||||
fn code(&self) -> i32 {
|
||||
EXIT_ERR
|
||||
}
|
||||
}
|
||||
|
||||
/// Continue next iteration of loop if result of expression is error
|
||||
macro_rules! or_continue(
|
||||
($expr:expr) => (match $expr {
|
||||
|
@ -220,7 +227,6 @@ pub struct Options {
|
|||
|
||||
static ABOUT: &str = "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.";
|
||||
static LONG_HELP: &str = "";
|
||||
static EXIT_OK: i32 = 0;
|
||||
static EXIT_ERR: i32 = 1;
|
||||
|
||||
fn usage() -> String {
|
||||
|
@ -446,7 +452,8 @@ pub fn uu_app() -> App<'static, 'static> {
|
|||
.multiple(true))
|
||||
}
|
||||
|
||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
#[uucore_procs::gen_uumain]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let usage = usage();
|
||||
let matches = uu_app()
|
||||
.after_help(&*format!(
|
||||
|
@ -457,11 +464,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
.usage(&usage[..])
|
||||
.get_matches_from(args);
|
||||
|
||||
let options = crash_if_err!(EXIT_ERR, Options::from_matches(&matches));
|
||||
let options = Options::from_matches(&matches)?;
|
||||
|
||||
if options.overwrite == OverwriteMode::NoClobber && options.backup != BackupMode::NoBackup {
|
||||
show_usage_error!("options --backup and --no-clobber are mutually exclusive");
|
||||
return 1;
|
||||
return Err(ExitCode(EXIT_ERR).into());
|
||||
}
|
||||
|
||||
let paths: Vec<String> = matches
|
||||
|
@ -469,7 +476,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
.map(|v| v.map(ToString::to_string).collect())
|
||||
.unwrap_or_default();
|
||||
|
||||
let (sources, target) = crash_if_err!(EXIT_ERR, parse_path_args(&paths, &options));
|
||||
let (sources, target) = parse_path_args(&paths, &options)?;
|
||||
|
||||
if let Err(error) = copy(&sources, &target, &options) {
|
||||
match error {
|
||||
|
@ -479,10 +486,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
// Else we caught a fatal bubbled-up error, log it to stderr
|
||||
_ => show_error!("{}", error),
|
||||
};
|
||||
return EXIT_ERR;
|
||||
set_exit_code(EXIT_ERR);
|
||||
}
|
||||
|
||||
EXIT_OK
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl ClobberMode {
|
||||
|
@ -1124,7 +1131,7 @@ fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResu
|
|||
let xattrs = xattr::list(source)?;
|
||||
for attr in xattrs {
|
||||
if let Some(attr_value) = xattr::get(source, attr.clone())? {
|
||||
crash_if_err!(EXIT_ERR, xattr::set(dest, attr, &attr_value[..]));
|
||||
xattr::set(dest, attr, &attr_value[..])?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
// For the full copyright and license information, please view the LICENSE file
|
||||
// that was distributed with this source code.
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
use uucore::error::UError;
|
||||
use uucore::error::UResult;
|
||||
#[cfg(unix)]
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{crate_version, App, Arg};
|
||||
use std::path::Path;
|
||||
use uucore::display::print_verbatim;
|
||||
|
|
|
@ -6,9 +6,6 @@
|
|||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{crate_version, App, Arg};
|
||||
use std::io::{self, Write};
|
||||
use std::iter::Peekable;
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
//* For the full copyright and license information, please view the LICENSE
|
||||
//* file that was distributed with this source code.
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{crate_version, App, Arg};
|
||||
use uucore::error::{UResult, USimpleError};
|
||||
use uucore::InvalidEncodingHandling;
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
// * For the full copyright and license information, please view the LICENSE
|
||||
// * file that was distributed with this source code.
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::App;
|
||||
use uucore::error::UResult;
|
||||
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
|
||||
// spell-checker:ignore (ToDO) gethostid
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{crate_version, App};
|
||||
use libc::c_long;
|
||||
use uucore::error::UResult;
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
|
||||
// spell-checker:ignore (ToDO) MAKEWORD addrs hashset
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::collections::hash_set::HashSet;
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::str;
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
|
||||
// spell-checker:ignore (paths) GPGHome
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{crate_version, App, Arg};
|
||||
use uucore::display::{println_verbatim, Quotable};
|
||||
use uucore::error::{FromIo, UError, UResult};
|
||||
|
|
|
@ -20,7 +20,7 @@ use quick_error::ResultExt;
|
|||
use regex::Regex;
|
||||
use std::convert::From;
|
||||
use std::fs::{metadata, File};
|
||||
use std::io::{stdin, stdout, BufRead, BufReader, Lines, Read, Stdout, Write};
|
||||
use std::io::{stdin, stdout, BufRead, BufReader, Lines, Read, Write};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::fs::FileTypeExt;
|
||||
|
||||
|
@ -1036,15 +1036,16 @@ fn print_page(lines: &[FileLine], options: &OutputOptions, page: usize) -> Resul
|
|||
|
||||
let header = header_content(options, page);
|
||||
let trailer_content = trailer_content(options);
|
||||
let out = &mut stdout();
|
||||
|
||||
out.lock();
|
||||
let out = stdout();
|
||||
let mut out = out.lock();
|
||||
|
||||
for x in header {
|
||||
out.write_all(x.as_bytes())?;
|
||||
out.write_all(line_separator)?;
|
||||
}
|
||||
|
||||
let lines_written = write_columns(lines, options, out)?;
|
||||
let lines_written = write_columns(lines, options, &mut out)?;
|
||||
|
||||
for (index, x) in trailer_content.iter().enumerate() {
|
||||
out.write_all(x.as_bytes())?;
|
||||
|
@ -1060,7 +1061,7 @@ fn print_page(lines: &[FileLine], options: &OutputOptions, page: usize) -> Resul
|
|||
fn write_columns(
|
||||
lines: &[FileLine],
|
||||
options: &OutputOptions,
|
||||
out: &mut Stdout,
|
||||
out: &mut impl Write,
|
||||
) -> Result<usize, IOError> {
|
||||
let line_separator = options.content_line_separator.as_bytes();
|
||||
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
// * For the full copyright and license information, please view the LICENSE
|
||||
// * file that was distributed with this source code.
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{crate_version, App, Arg};
|
||||
use std::env;
|
||||
use std::io;
|
||||
|
|
|
@ -88,30 +88,65 @@ impl FromStr for Number {
|
|||
if s.starts_with('+') {
|
||||
s = &s[1..];
|
||||
}
|
||||
let is_neg = s.starts_with('-');
|
||||
|
||||
match s.parse::<BigInt>() {
|
||||
Ok(n) => {
|
||||
// If `s` is '-0', then `parse()` returns
|
||||
// `BigInt::zero()`, but we need to return
|
||||
// `Number::MinusZero` instead.
|
||||
if n == BigInt::zero() && s.starts_with('-') {
|
||||
Ok(Number::MinusZero)
|
||||
} else {
|
||||
Ok(Number::BigInt(n))
|
||||
match s.to_lowercase().find("0x") {
|
||||
Some(i) if i <= 1 => match &s.as_bytes()[i + 2] {
|
||||
b'-' | b'+' => Err(format!(
|
||||
"invalid hexadecimal argument: {}\nTry '{} --help' for more information.",
|
||||
s.quote(),
|
||||
uucore::execution_phrase(),
|
||||
)),
|
||||
// TODO: hexadecimal floating point parsing (see #2660)
|
||||
b'.' => Err(format!(
|
||||
"NotImplemented: hexadecimal floating point numbers: {}\nTry '{} --help' for more information.",
|
||||
s.quote(),
|
||||
uucore::execution_phrase(),
|
||||
)),
|
||||
_ => {
|
||||
let num = BigInt::from_str_radix(&s[i + 2..], 16)
|
||||
.map_err(|_| format!(
|
||||
"invalid hexadecimal argument: {}\nTry '{} --help' for more information.",
|
||||
s.quote(),
|
||||
uucore::execution_phrase(),
|
||||
))?;
|
||||
match (is_neg, num == BigInt::zero()) {
|
||||
(true, true) => Ok(Number::MinusZero),
|
||||
(true, false) => Ok(Number::BigInt(-num)),
|
||||
(false, _) => Ok(Number::BigInt(num)),
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(_) => Err(format!(
|
||||
"invalid hexadecimal argument: {}\nTry '{} --help' for more information.",
|
||||
s.quote(),
|
||||
uucore::execution_phrase(),
|
||||
)),
|
||||
|
||||
None => match s.parse::<BigInt>() {
|
||||
Ok(n) => {
|
||||
// If `s` is '-0', then `parse()` returns
|
||||
// `BigInt::zero()`, but we need to return
|
||||
// `Number::MinusZero` instead.
|
||||
if n == BigInt::zero() && is_neg {
|
||||
Ok(Number::MinusZero)
|
||||
} else {
|
||||
Ok(Number::BigInt(n))
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => match s.parse::<f64>() {
|
||||
Ok(value) if value.is_nan() => Err(format!(
|
||||
Err(_) => match s.parse::<f64>() {
|
||||
Ok(value) if value.is_nan() => Err(format!(
|
||||
"invalid 'not-a-number' argument: {}\nTry '{} --help' for more information.",
|
||||
s.quote(),
|
||||
uucore::execution_phrase(),
|
||||
)),
|
||||
Ok(value) => Ok(Number::F64(value)),
|
||||
Err(_) => Err(format!(
|
||||
Ok(value) => Ok(Number::F64(value)),
|
||||
Err(_) => Err(format!(
|
||||
"invalid floating point argument: {}\nTry '{} --help' for more information.",
|
||||
s.quote(),
|
||||
uucore::execution_phrase(),
|
||||
)),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
// * For the full copyright and license information, please view the LICENSE
|
||||
// * file that was distributed with this source code.
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
// * For the full copyright and license information, please view the LICENSE
|
||||
// * file that was distributed with this source code.
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::App;
|
||||
use uucore::error::UResult;
|
||||
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
|
||||
/* last synced with: unlink (GNU coreutils) 8.21 */
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::fs::remove_file;
|
||||
use std::path::Path;
|
||||
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
use chrono::{Local, TimeZone, Utc};
|
||||
use clap::{crate_version, App, Arg};
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
// import crate time from utmpx
|
||||
pub use uucore::libc;
|
||||
use uucore::libc::time_t;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
use std::path::Path;
|
||||
|
||||
use clap::{crate_version, App, Arg};
|
||||
use uucore::error::UResult;
|
||||
use uucore::utmpx::{self, Utmpx};
|
||||
|
||||
static ABOUT: &str = "Print the user names of users currently logged in to the current host";
|
||||
|
@ -29,7 +30,8 @@ If FILE is not specified, use {}. /var/log/wtmp as FILE is common.",
|
|||
)
|
||||
}
|
||||
|
||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
#[uucore_procs::gen_uumain]
|
||||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let usage = usage();
|
||||
let after_help = get_long_usage();
|
||||
|
||||
|
@ -59,7 +61,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
|
|||
println!("{}", users.join(" "));
|
||||
}
|
||||
|
||||
0
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn uu_app() -> App<'static, 'static> {
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::App;
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@ use std::io::{self, Write};
|
|||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use clap::{App, Arg};
|
||||
use uucore::error::{UResult, USimpleError};
|
||||
|
|
|
@ -101,7 +101,7 @@ pub fn gen_uumain(_args: TokenStream, stream: TokenStream) -> TokenStream {
|
|||
Err(e) => {
|
||||
let s = format!("{}", e);
|
||||
if s != "" {
|
||||
show_error!("{}", s);
|
||||
uucore::show_error!("{}", s);
|
||||
}
|
||||
if e.usage() {
|
||||
eprintln!("Try '{} --help' for more information.", uucore::execution_phrase());
|
||||
|
|
|
@ -15,6 +15,7 @@ fn test_missing_operand() {
|
|||
|
||||
#[test]
|
||||
fn test_enter_chroot_fails() {
|
||||
// NOTE: since #2689 this test also ensures that we don't regress #2687
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
|
||||
at.mkdir("jail");
|
||||
|
@ -89,3 +90,26 @@ fn test_preference_of_userspec() {
|
|||
println!("result.stdout = {}", result.stdout_str());
|
||||
println!("result.stderr = {}", result.stderr_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_shell() {
|
||||
// NOTE: This test intends to trigger code which can only be reached with root permissions.
|
||||
let ts = TestScenario::new(util_name!());
|
||||
let at = &ts.fixtures;
|
||||
|
||||
let dir = "CHROOT_DIR";
|
||||
at.mkdir(dir);
|
||||
|
||||
let shell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string());
|
||||
let _expected = format!(
|
||||
"chroot: failed to run command '{}': No such file or directory",
|
||||
shell
|
||||
);
|
||||
|
||||
// TODO: [2021-09; jhscheer] uncomment if/when #2692 gets merged
|
||||
// if let Ok(result) = run_ucmd_as_root(&ts, &[dir]) {
|
||||
// result.stderr_contains(expected);
|
||||
// } else {
|
||||
// print!("TEST SKIPPED");
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -28,9 +28,7 @@ macro_rules! fixture_path {
|
|||
macro_rules! assert_fixture_exists {
|
||||
($fname:expr) => {{
|
||||
let fpath = fixture_path!($fname);
|
||||
if !fpath.exists() {
|
||||
panic!("Fixture missing: {:?}", fpath);
|
||||
}
|
||||
assert!(fpath.exists(), "Fixture missing: {:?}", fpath);
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -38,9 +36,7 @@ macro_rules! assert_fixture_exists {
|
|||
macro_rules! assert_fixture_not_exists {
|
||||
($fname:expr) => {{
|
||||
let fpath = PathBuf::from(format!("./fixtures/dd/{}", $fname));
|
||||
if fpath.exists() {
|
||||
panic!("Fixture present: {:?}", fpath);
|
||||
}
|
||||
assert!(!fpath.exists(), "Fixture present: {:?}", fpath);
|
||||
}};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// spell-checker:ignore abcdefghijklmnopqrstuvwxyz
|
||||
// * This file is part of the uutils coreutils package.
|
||||
// *
|
||||
// * For the full copyright and license information, please view the LICENSE
|
||||
|
@ -35,9 +36,10 @@ fn test_file() {
|
|||
{
|
||||
let mut f = File::create(&file).unwrap();
|
||||
// spell-checker:disable-next-line
|
||||
if f.write_all(b"abcdefghijklmnopqrstuvwxyz\n").is_err() {
|
||||
panic!("Test setup failed - could not write file");
|
||||
}
|
||||
assert!(
|
||||
!f.write_all(b"abcdefghijklmnopqrstuvwxyz\n").is_err(),
|
||||
"Test setup failed - could not write file"
|
||||
);
|
||||
}
|
||||
|
||||
new_ucmd!()
|
||||
|
@ -75,9 +77,10 @@ fn test_2files() {
|
|||
// spell-checker:disable-next-line
|
||||
for &(path, data) in &[(&file1, "abcdefghijklmnop"), (&file2, "qrstuvwxyz\n")] {
|
||||
let mut f = File::create(&path).unwrap();
|
||||
if f.write_all(data.as_bytes()).is_err() {
|
||||
panic!("Test setup failed - could not write file");
|
||||
}
|
||||
assert!(
|
||||
!f.write_all(data.as_bytes()).is_err(),
|
||||
"Test setup failed - could not write file"
|
||||
);
|
||||
}
|
||||
|
||||
new_ucmd!()
|
||||
|
@ -126,9 +129,10 @@ fn test_from_mixed() {
|
|||
let (data1, data2, data3) = ("abcdefg", "hijklmnop", "qrstuvwxyz\n");
|
||||
for &(path, data) in &[(&file1, data1), (&file3, data3)] {
|
||||
let mut f = File::create(&path).unwrap();
|
||||
if f.write_all(data.as_bytes()).is_err() {
|
||||
panic!("Test setup failed - could not write file");
|
||||
}
|
||||
assert!(
|
||||
!f.write_all(data.as_bytes()).is_err(),
|
||||
"Test setup failed - could not write file"
|
||||
);
|
||||
}
|
||||
|
||||
new_ucmd!()
|
||||
|
|
|
@ -1,6 +1,69 @@
|
|||
use crate::common::util::*;
|
||||
use std::io::Read;
|
||||
|
||||
#[test]
|
||||
fn test_hex_rejects_sign_after_identifier() {
|
||||
new_ucmd!()
|
||||
.args(&["0x-123ABC"])
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("invalid hexadecimal argument: '0x-123ABC'")
|
||||
.stderr_contains("for more information.");
|
||||
new_ucmd!()
|
||||
.args(&["0x+123ABC"])
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("invalid hexadecimal argument: '0x+123ABC'")
|
||||
.stderr_contains("for more information.");
|
||||
new_ucmd!()
|
||||
.args(&["-0x-123ABC"])
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("invalid hexadecimal argument: '-0x-123ABC'")
|
||||
.stderr_contains("for more information.");
|
||||
new_ucmd!()
|
||||
.args(&["-0x+123ABC"])
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("invalid hexadecimal argument: '-0x+123ABC'")
|
||||
.stderr_contains("for more information.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hex_lowercase_uppercase() {
|
||||
new_ucmd!()
|
||||
.args(&["0xa", "0xA"])
|
||||
.succeeds()
|
||||
.stdout_is("10\n");
|
||||
new_ucmd!()
|
||||
.args(&["0Xa", "0XA"])
|
||||
.succeeds()
|
||||
.stdout_is("10\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hex_big_number() {
|
||||
new_ucmd!()
|
||||
.args(&[
|
||||
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"0x100000000000000000000000000000000",
|
||||
])
|
||||
.succeeds()
|
||||
.stdout_is(
|
||||
"340282366920938463463374607431768211455\n340282366920938463463374607431768211456\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hex_identifier_in_wrong_place() {
|
||||
new_ucmd!()
|
||||
.args(&["1234ABCD0x"])
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("invalid hexadecimal argument: '1234ABCD0x'")
|
||||
.stderr_contains("for more information.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rejects_nan() {
|
||||
let ts = TestScenario::new(util_name!());
|
||||
|
|
|
@ -163,25 +163,23 @@ impl CmdResult {
|
|||
|
||||
/// asserts that the command resulted in a success (zero) status code
|
||||
pub fn success(&self) -> &CmdResult {
|
||||
if !self.success {
|
||||
panic!(
|
||||
"Command was expected to succeed.\nstdout = {}\n stderr = {}",
|
||||
self.stdout_str(),
|
||||
self.stderr_str()
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
self.success,
|
||||
"Command was expected to succeed.\nstdout = {}\n stderr = {}",
|
||||
self.stdout_str(),
|
||||
self.stderr_str()
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
/// asserts that the command resulted in a failure (non-zero) status code
|
||||
pub fn failure(&self) -> &CmdResult {
|
||||
if self.success {
|
||||
panic!(
|
||||
"Command was expected to fail.\nstdout = {}\n stderr = {}",
|
||||
self.stdout_str(),
|
||||
self.stderr_str()
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!self.success,
|
||||
"Command was expected to fail.\nstdout = {}\n stderr = {}",
|
||||
self.stdout_str(),
|
||||
self.stderr_str()
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -197,12 +195,11 @@ impl CmdResult {
|
|||
/// 1. you can not know exactly what stdout will be or
|
||||
/// 2. you know that stdout will also be empty
|
||||
pub fn no_stderr(&self) -> &CmdResult {
|
||||
if !self.stderr.is_empty() {
|
||||
panic!(
|
||||
"Expected stderr to be empty, but it's:\n{}",
|
||||
self.stderr_str()
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
self.stderr.is_empty(),
|
||||
"Expected stderr to be empty, but it's:\n{}",
|
||||
self.stderr_str()
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -213,12 +210,11 @@ impl CmdResult {
|
|||
/// 1. you can not know exactly what stderr will be or
|
||||
/// 2. you know that stderr will also be empty
|
||||
pub fn no_stdout(&self) -> &CmdResult {
|
||||
if !self.stdout.is_empty() {
|
||||
panic!(
|
||||
"Expected stdout to be empty, but it's:\n{}",
|
||||
self.stderr_str()
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
self.stdout.is_empty(),
|
||||
"Expected stdout to be empty, but it's:\n{}",
|
||||
self.stderr_str()
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -868,9 +864,7 @@ impl UCommand {
|
|||
/// Add a parameter to the invocation. Path arguments are treated relative
|
||||
/// to the test environment directory.
|
||||
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut UCommand {
|
||||
if self.has_run {
|
||||
panic!("{}", ALREADY_RUN);
|
||||
}
|
||||
assert!(!self.has_run, ALREADY_RUN);
|
||||
self.comm_string.push(' ');
|
||||
self.comm_string
|
||||
.push_str(arg.as_ref().to_str().unwrap_or_default());
|
||||
|
@ -881,9 +875,7 @@ impl UCommand {
|
|||
/// Add multiple parameters to the invocation. Path arguments are treated relative
|
||||
/// to the test environment directory.
|
||||
pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> &mut UCommand {
|
||||
if self.has_run {
|
||||
panic!("{}", MULTIPLE_STDIN_MEANINGLESS);
|
||||
}
|
||||
assert!(!self.has_run, MULTIPLE_STDIN_MEANINGLESS);
|
||||
let strings = args
|
||||
.iter()
|
||||
.map(|s| s.as_ref().to_os_string())
|
||||
|
@ -901,9 +893,7 @@ impl UCommand {
|
|||
|
||||
/// provides standard input to feed in to the command when spawned
|
||||
pub fn pipe_in<T: Into<Vec<u8>>>(&mut self, input: T) -> &mut UCommand {
|
||||
if self.bytes_into_stdin.is_some() {
|
||||
panic!("{}", MULTIPLE_STDIN_MEANINGLESS);
|
||||
}
|
||||
assert!(!self.bytes_into_stdin.is_some(), MULTIPLE_STDIN_MEANINGLESS);
|
||||
self.bytes_into_stdin = Some(input.into());
|
||||
self
|
||||
}
|
||||
|
@ -918,9 +908,7 @@ impl UCommand {
|
|||
/// This is typically useful to test non-standard workflows
|
||||
/// like feeding something to a command that does not read it
|
||||
pub fn ignore_stdin_write_error(&mut self) -> &mut UCommand {
|
||||
if self.bytes_into_stdin.is_none() {
|
||||
panic!("{}", NO_STDIN_MEANINGLESS);
|
||||
}
|
||||
assert!(!self.bytes_into_stdin.is_none(), NO_STDIN_MEANINGLESS);
|
||||
self.ignore_stdin_write_error = true;
|
||||
self
|
||||
}
|
||||
|
@ -930,9 +918,7 @@ impl UCommand {
|
|||
K: AsRef<OsStr>,
|
||||
V: AsRef<OsStr>,
|
||||
{
|
||||
if self.has_run {
|
||||
panic!("{}", ALREADY_RUN);
|
||||
}
|
||||
assert!(!self.has_run, ALREADY_RUN);
|
||||
self.raw.env(key, val);
|
||||
self
|
||||
}
|
||||
|
@ -951,9 +937,7 @@ impl UCommand {
|
|||
/// Spawns the command, feeds the stdin if any, and returns the
|
||||
/// child process immediately.
|
||||
pub fn run_no_wait(&mut self) -> Child {
|
||||
if self.has_run {
|
||||
panic!("{}", ALREADY_RUN);
|
||||
}
|
||||
assert!(!self.has_run, ALREADY_RUN);
|
||||
self.has_run = true;
|
||||
log_info("run", &self.comm_string);
|
||||
let mut child = self
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
set -e
|
||||
if test ! -d ../gnu; then
|
||||
echo "Could not find ../gnu"
|
||||
echo "git clone git@github.com:coreutils/coreutils.git gnu"
|
||||
echo "git clone https://github.com:coreutils/coreutils.git gnu"
|
||||
exit 1
|
||||
fi
|
||||
if test ! -d ../gnulib; then
|
||||
echo "Could not find ../gnulib"
|
||||
echo "git clone git@github.com:coreutils/gnulib.git gnulib"
|
||||
echo "git clone https://github.com/coreutils/gnulib.git gnulib"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue