1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-09-16 19:56:17 +00:00

Merge branch 'main' into hbina-tr-reimplement-expansion

This commit is contained in:
Terts Diepraam 2022-01-19 19:31:54 +01:00
commit da728dd2b6
338 changed files with 5042 additions and 38041 deletions

View file

@ -74,9 +74,8 @@ fn test_invalid_file() {
at.mkdir(folder_name);
ts.ucmd()
.arg(folder_name)
.fails()
.no_stdout()
.stderr_contains("cksum: asdf: Is a directory");
.succeeds()
.stdout_only("4294967295 0 asdf\n");
}
// Make sure crc is correct for files larger than 32 bytes

View file

@ -170,3 +170,11 @@ fn no_arguments() {
fn one_argument() {
new_ucmd!().arg("a").fails().no_stdout().no_stderr();
}
#[test]
fn test_no_such_file() {
new_ucmd!()
.args(&["bogus_file_1", "bogus_file_2"])
.fails()
.stderr_only("comm: bogus_file_1: No such file or directory");
}

View file

@ -725,6 +725,21 @@ fn test_cp_parents_dest_not_directory() {
.stderr_contains("with --parents, the destination must be a directory");
}
#[test]
#[cfg(unix)]
fn test_cp_writable_special_file_permissions() {
new_ucmd!().arg("/dev/null").arg("/dev/zero").succeeds();
}
#[test]
#[cfg(unix)]
fn test_cp_issue_1665() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.arg("/dev/null").arg("foo").succeeds();
assert!(at.file_exists("foo"));
assert_eq!(at.read("foo"), "");
}
#[test]
fn test_cp_preserve_no_args() {
new_ucmd!()
@ -1364,3 +1379,42 @@ fn test_canonicalize_symlink() {
.no_stderr()
.no_stdout();
}
#[test]
fn test_copy_through_just_created_symlink() {
for &create_t in &[true, false] {
let (at, mut ucmd) = at_and_ucmd!();
at.mkdir("a");
at.mkdir("b");
at.mkdir("c");
#[cfg(unix)]
fs::symlink("../t", at.plus("a/1")).unwrap();
#[cfg(target_os = "windows")]
symlink_file("../t", at.plus("a/1")).unwrap();
at.touch("b/1");
if create_t {
at.touch("t");
}
ucmd.arg("--no-dereference")
.arg("a/1")
.arg("b/1")
.arg("c")
.fails()
.stderr_only(if cfg!(not(target_os = "windows")) {
"cp: will not copy 'b/1' through just-created symlink 'c/1'"
} else {
"cp: will not copy 'b/1' through just-created symlink 'c\\1'"
});
}
}
#[test]
fn test_copy_through_dangling_symlink() {
let (at, mut ucmd) = at_and_ucmd!();
at.touch("file");
at.symlink_file("nonexistent", "target");
ucmd.arg("file")
.arg("target")
.fails()
.stderr_only("cp: not writing through dangling symlink 'target'");
}

View file

@ -262,7 +262,9 @@ fn test_nocreat_causes_failure_when_outfile_not_present() {
ucmd.args(&["conv=nocreat", of!(&fname)])
.pipe_in("")
.fails()
.stderr_is("dd Error: No such file or directory (os error 2)");
.stderr_only(
"dd: failed to open 'this-file-does-not-exist.txt': No such file or directory",
);
assert!(!fix.file_exists(fname));
}

View file

@ -328,3 +328,31 @@ fn single_file_with_header() {
.succeeds()
.stdout_is("A 1\n");
}
#[test]
fn non_line_feeds() {
new_ucmd!()
.arg("non-line_feeds_1.txt")
.arg("non-line_feeds_2.txt")
.succeeds()
.stdout_only_fixture("non-line_feeds.expected");
}
#[test]
fn non_unicode() {
new_ucmd!()
.arg("non-unicode_1.bin")
.arg("non-unicode_2.bin")
.succeeds()
.stdout_only_fixture("non-unicode.expected");
}
#[test]
fn null_line_endings() {
new_ucmd!()
.arg("-z")
.arg("non-unicode_1.bin")
.arg("non-unicode_2.bin")
.succeeds()
.stdout_only_fixture("z.expected");
}

View file

@ -23,7 +23,7 @@ fn test_link_no_circular() {
ucmd.args(&[link, link])
.fails()
.stderr_is("link: No such file or directory (os error 2)\n");
.stderr_is("link: cannot create link 'test_link_no_circular' to 'test_link_no_circular': No such file or directory");
assert!(!at.file_exists(link));
}
@ -35,7 +35,7 @@ fn test_link_nonexistent_file() {
ucmd.args(&[file, link])
.fails()
.stderr_is("link: No such file or directory (os error 2)\n");
.stderr_only("link: cannot create link 'test_link_nonexistent_file_link' to 'test_link_nonexistent_file': No such file or directory");
assert!(!at.file_exists(file));
assert!(!at.file_exists(link));
}

View file

@ -11,7 +11,6 @@ use std::collections::HashMap;
use std::path::Path;
use std::thread::sleep;
use std::time::Duration;
#[cfg(not(windows))]
extern crate libc;
#[cfg(not(windows))]
@ -40,6 +39,198 @@ fn test_ls_i() {
}
#[test]
fn test_ls_ordering() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.mkdir("some-dir1");
at.mkdir("some-dir2");
at.mkdir("some-dir3");
at.mkdir("some-dir4");
at.mkdir("some-dir5");
at.mkdir("some-dir6");
scene
.ucmd()
.arg("-Rl")
.succeeds()
.stdout_matches(&Regex::new("some-dir1:\\ntotal 0").unwrap());
}
//#[cfg(all(feature = "mknod"))]
#[test]
fn test_ls_devices() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.mkdir("some-dir1");
// Regex tests correct device ID and correct (no pad) spacing for a single file
#[cfg(any(target_os = "macos", target_os = "ios"))]
{
scene
.ucmd()
.arg("-al")
.arg("/dev/null")
.succeeds()
.stdout_matches(&Regex::new("[^ ] 3, 2 [^ ]").unwrap());
}
#[cfg(target_os = "linux")]
{
scene
.ucmd()
.arg("-al")
.arg("/dev/null")
.succeeds()
.stdout_matches(&Regex::new("[^ ] 1, 3 [^ ]").unwrap());
}
// Regex tests alignment against a file (stdout is a link to a tty)
#[cfg(unix)]
{
let res = scene
.ucmd()
.arg("-alL")
.arg("/dev/null")
.arg("/dev/stdout")
.succeeds();
let null_len = String::from_utf8(res.stdout().to_owned())
.ok()
.unwrap()
.lines()
.next()
.unwrap()
.strip_suffix("/dev/null")
.unwrap()
.len();
let stdout_len = String::from_utf8(res.stdout().to_owned())
.ok()
.unwrap()
.lines()
.nth(1)
.unwrap()
.strip_suffix("/dev/stdout")
.unwrap()
.len();
assert_eq!(stdout_len, null_len);
}
}
#[cfg(all(feature = "chmod"))]
#[test]
fn test_ls_io_errors() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.mkdir("some-dir1");
at.mkdir("some-dir2");
at.symlink_file("does_not_exist", "some-dir2/dangle");
at.mkdir("some-dir3");
at.mkdir("some-dir3/some-dir4");
at.mkdir("some-dir3/some-dir5");
at.mkdir("some-dir3/some-dir6");
at.mkdir("some-dir3/some-dir7");
at.mkdir("some-dir3/some-dir8");
scene.ccmd("chmod").arg("000").arg("some-dir1").succeeds();
scene
.ucmd()
.arg("-1")
.arg("some-dir1")
.fails()
.stderr_contains("cannot open directory")
.stderr_contains("Permission denied");
scene
.ucmd()
.arg("-Li")
.arg("some-dir2")
.fails()
.stderr_contains("cannot access")
.stderr_contains("No such file or directory")
.stdout_contains(if cfg!(windows) { "dangle" } else { "? dangle" });
scene
.ccmd("chmod")
.arg("000")
.arg("some-dir3/some-dir4")
.succeeds();
scene
.ucmd()
.arg("-laR")
.arg("some-dir3")
.fails()
.stderr_contains("some-dir4")
.stderr_contains("cannot open directory")
.stderr_contains("Permission denied")
.stdout_contains("some-dir4");
// test we don't double print on dangling link metadata errors
scene
.ucmd()
.arg("-iRL")
.arg("some-dir2")
.fails()
.stderr_does_not_contain(
"ls: cannot access 'some-dir2/dangle': No such file or directory\nls: cannot access 'some-dir2/dangle': No such file or directory"
);
}
#[test]
fn test_ls_only_dirs_formatting() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.mkdir("some-dir1");
at.mkdir("some-dir2");
at.mkdir("some-dir3");
#[cfg(unix)]
{
scene.ucmd().arg("-1").arg("-R").succeeds().stdout_only(
".:\nsome-dir1\nsome-dir2\nsome-dir3\n\n./some-dir1:\n\n./some-dir2:\n\n./some-dir3:\n",
);
}
#[cfg(windows)]
{
scene.ucmd().arg("-1").arg("-R").succeeds().stdout_only(
".:\nsome-dir1\nsome-dir2\nsome-dir3\n\n.\\some-dir1:\n\n.\\some-dir2:\n\n.\\some-dir3:\n",
);
}
}
#[test]
fn test_ls_walk_glob() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.touch(".test-1");
at.mkdir("some-dir");
at.touch(
Path::new("some-dir")
.join("test-2~")
.as_os_str()
.to_str()
.unwrap(),
);
#[allow(clippy::trivial_regex)]
let re_pwd = Regex::new(r"^\.\n").unwrap();
scene
.ucmd()
.arg("-1")
.arg("--ignore-backups")
.arg("some-dir")
.succeeds()
.stdout_does_not_contain("test-2~")
.stdout_does_not_contain("..")
.stdout_does_not_match(&re_pwd);
}
#[test]
#[cfg(unix)]
fn test_ls_a() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
@ -1523,6 +1714,41 @@ fn test_ls_hidden_windows() {
scene.ucmd().arg("-a").succeeds().stdout_contains(file);
}
#[cfg(windows)]
#[test]
fn test_ls_hidden_link_windows() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let file = "visibleWindowsFileNoDot";
at.touch(file);
let link = "hiddenWindowsLinkNoDot";
at.symlink_dir(file, link);
// hide the link
scene.cmd("attrib").arg("/l").arg("+h").arg(link).succeeds();
scene
.ucmd()
.succeeds()
.stdout_contains(file)
.stdout_does_not_contain(link);
scene
.ucmd()
.arg("-a")
.succeeds()
.stdout_contains(file)
.stdout_contains(link);
}
#[cfg(windows)]
#[test]
fn test_ls_success_on_c_drv_root_windows() {
let scene = TestScenario::new(util_name!());
scene.ucmd().arg("C:\\").succeeds();
}
#[test]
fn test_ls_version_sort() {
let scene = TestScenario::new(util_name!());
@ -1903,6 +2129,7 @@ fn test_ls_ignore_hide() {
}
#[test]
#[cfg(unix)]
fn test_ls_ignore_backups() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
@ -2269,12 +2496,59 @@ fn test_ls_dangling_symlinks() {
.succeeds()
.stdout_contains("dangle");
#[cfg(not(windows))]
scene
.ucmd()
.arg("-Li")
.arg("temp_dir")
.succeeds() // this should fail, though at the moment, ls lacks a way to propagate errors encountered during display
.stdout_contains(if cfg!(windows) { "dangle" } else { "? dangle" });
.fails()
.stderr_contains("cannot access")
.stdout_contains("? dangle");
#[cfg(windows)]
scene
.ucmd()
.arg("-Li")
.arg("temp_dir")
.succeeds()
.stdout_contains("dangle");
scene
.ucmd()
.arg("-Ll")
.arg("temp_dir")
.fails()
.stdout_contains("l?????????");
#[cfg(unix)]
{
// Check padding is the same for real files and dangling links, in non-long formats
at.touch("temp_dir/real_file");
let real_file_res = scene.ucmd().arg("-Li1").arg("temp_dir").fails();
let real_file_stdout_len = String::from_utf8(real_file_res.stdout().to_owned())
.ok()
.unwrap()
.lines()
.nth(1)
.unwrap()
.strip_suffix("real_file")
.unwrap()
.len();
let dangle_file_res = scene.ucmd().arg("-Li1").arg("temp_dir").fails();
let dangle_stdout_len = String::from_utf8(dangle_file_res.stdout().to_owned())
.ok()
.unwrap()
.lines()
.next()
.unwrap()
.strip_suffix("dangle")
.unwrap()
.len();
assert_eq!(real_file_stdout_len, dangle_stdout_len);
}
}
#[test]

View file

@ -232,6 +232,40 @@ fn test_mv_force_replace_file() {
assert!(at.file_exists(file_b));
}
#[test]
fn test_mv_same_file() {
let (at, mut ucmd) = at_and_ucmd!();
let file_a = "test_mv_same_file_a";
at.touch(file_a);
ucmd.arg(file_a).arg(file_a).fails().stderr_is(format!(
"mv: '{f}' and '{f}' are the same file\n",
f = file_a,
));
}
#[test]
fn test_mv_same_file_not_dot_dir() {
let (at, mut ucmd) = at_and_ucmd!();
let dir = "test_mv_errors_dir";
at.mkdir(dir);
ucmd.arg(dir).arg(dir).fails().stderr_is(format!(
"mv: cannot move '{d}' to a subdirectory of itself, '{d}/{d}'",
d = dir,
));
}
#[test]
fn test_mv_same_file_dot_dir() {
let (_at, mut ucmd) = at_and_ucmd!();
ucmd.arg(".")
.arg(".")
.fails()
.stderr_is("mv: '.' and '.' are the same file\n".to_string());
}
#[test]
fn test_mv_simple_backup() {
let (at, mut ucmd) = at_and_ucmd!();

View file

@ -505,3 +505,66 @@ fn test_round() {
.stdout_only(exp.join("\n") + "\n");
}
}
#[test]
fn test_suffix_is_added_if_not_supplied() {
new_ucmd!()
.args(&["--suffix=TEST"])
.pipe_in("1000")
.succeeds()
.stdout_only("1000TEST\n");
}
#[test]
fn test_suffix_is_preserved() {
new_ucmd!()
.args(&["--suffix=TEST"])
.pipe_in("1000TEST")
.succeeds()
.stdout_only("1000TEST\n");
}
#[test]
fn test_suffix_is_only_applied_to_selected_field() {
new_ucmd!()
.args(&["--suffix=TEST", "--field=2"])
.pipe_in("1000 2000 3000")
.succeeds()
.stdout_only("1000 2000TEST 3000\n");
}
#[test]
fn test_transform_with_suffix_on_input() {
new_ucmd!()
.args(&["--suffix=b", "--to=si"])
.pipe_in("2000b")
.succeeds()
.stdout_only("2.0Kb\n");
}
#[test]
fn test_transform_without_suffix_on_input() {
new_ucmd!()
.args(&["--suffix=b", "--to=si"])
.pipe_in("2000")
.succeeds()
.stdout_only("2.0Kb\n");
}
#[test]
fn test_transform_with_suffix_and_delimiter() {
new_ucmd!()
.args(&["--suffix=b", "--to=si", "-d=|"])
.pipe_in("1000b|2000|3000")
.succeeds()
.stdout_only("1.0Kb|2000|3000\n");
}
#[test]
fn test_suffix_with_padding() {
new_ucmd!()
.args(&["--suffix=pad", "--padding=12"])
.pipe_in("1000 2000 3000")
.succeeds()
.stdout_only(" 1000pad 2000 3000\n");
}

View file

@ -24,14 +24,11 @@ fn test_capitalize() {
fn test_long_format() {
let login = "root";
let pw: Passwd = Passwd::locate(login).unwrap();
let real_name = pw.user_info().replace("&", &pw.name().capitalize());
let real_name = pw.user_info.replace("&", &pw.name.capitalize());
let ts = TestScenario::new(util_name!());
ts.ucmd().arg("-l").arg(login).succeeds().stdout_is(format!(
"Login name: {:<28}In real life: {}\nDirectory: {:<29}Shell: {}\n\n",
login,
real_name,
pw.user_dir(),
pw.user_shell()
login, real_name, pw.user_dir, pw.user_shell
));
ts.ucmd()

View file

@ -280,7 +280,7 @@ fn test_rm_force_no_operand() {
fn test_rm_no_operand() {
let ts = TestScenario::new(util_name!());
ts.ucmd().fails().stderr_is(&format!(
"{0}: missing an argument\n{0}: for help, try '{1} {0} --help'\n",
"{0}: missing operand\nTry '{1} {0} --help' for more information.\n",
ts.util_name,
ts.bin_path.to_string_lossy()
));

View file

@ -1,3 +1,4 @@
// spell-checker:ignore lmnop xlmnop
use crate::common::util::*;
use std::io::Read;
@ -473,6 +474,15 @@ fn test_width_decimal_scientific_notation_trailing_zeros_increment() {
.no_stderr();
}
#[test]
fn test_width_negative_decimal_notation() {
new_ucmd!()
.args(&["-w", "-.1", ".1", ".11"])
.succeeds()
.stdout_is("-0.1\n00.0\n00.1\n")
.no_stderr();
}
#[test]
fn test_width_negative_scientific_notation() {
new_ucmd!()
@ -480,6 +490,54 @@ fn test_width_negative_scientific_notation() {
.succeeds()
.stdout_is("-0.001\n00.999\n")
.no_stderr();
new_ucmd!()
.args(&["-w", "-1.e-3", "1"])
.succeeds()
.stdout_is("-0.001\n00.999\n")
.no_stderr();
new_ucmd!()
.args(&["-w", "-1.0e-4", "1"])
.succeeds()
.stdout_is("-0.00010\n00.99990\n")
.no_stderr();
new_ucmd!()
.args(&["-w", "-.1e2", "10", "100"])
.succeeds()
.stdout_is(
"-010
0000
0010
0020
0030
0040
0050
0060
0070
0080
0090
0100
",
)
.no_stderr();
new_ucmd!()
.args(&["-w", "-0.1e2", "10", "100"])
.succeeds()
.stdout_is(
"-010
0000
0010
0020
0030
0040
0050
0060
0070
0080
0090
0100
",
)
.no_stderr();
}
/// Test that trailing zeros in the end argument do not contribute to width.
@ -619,3 +677,19 @@ fn test_rounding_end() {
.stdout_is("1\n")
.no_stderr();
}
#[test]
fn test_parse_error_float() {
new_ucmd!()
.arg("lmnop")
.fails()
.usage_error("invalid floating point argument: 'lmnop'");
}
#[test]
fn test_parse_error_hex() {
new_ucmd!()
.arg("0xlmnop")
.fails()
.usage_error("invalid hexadecimal argument: '0xlmnop'");
}

View file

@ -340,10 +340,10 @@ fn test_dictionary_order() {
fn test_dictionary_order2() {
for non_dictionary_order2_param in &["-d"] {
new_ucmd!()
.pipe_in("a👦🏻aa b\naaaa b") // spell-checker:disable-line
.pipe_in("a👦🏻aa\tb\naaaa\tb") // spell-checker:disable-line
.arg(non_dictionary_order2_param) // spell-checker:disable-line
.succeeds()
.stdout_only("a👦🏻aa b\naaaa b\n"); // spell-checker:disable-line
.stdout_only("a👦🏻aa\tb\naaaa\tb\n"); // spell-checker:disable-line
}
}
@ -918,6 +918,7 @@ fn test_compress_merge() {
#[test]
fn test_compress_fail() {
#[cfg(not(windows))]
TestScenario::new(util_name!())
.ucmd_keepenv()
.args(&[
@ -930,6 +931,21 @@ fn test_compress_fail() {
])
.fails()
.stderr_only("sort: couldn't execute compress program: errno 2");
// With coverage, it fails with a different error:
// "thread 'main' panicked at 'called `Option::unwrap()` on ...
// So, don't check the output
#[cfg(windows)]
TestScenario::new(util_name!())
.ucmd_keepenv()
.args(&[
"ext_sort.txt",
"-n",
"--compress-program",
"nonexistent-program",
"-S",
"10",
])
.fails();
}
#[test]

View file

@ -2,7 +2,7 @@
// *
// * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
// spell-checker:ignore xzaaa sixhundredfiftyonebytes ninetyonebytes asciilowercase
extern crate rand;
extern crate regex;
@ -16,7 +16,7 @@ use std::io::Write;
use std::path::Path;
use std::{
fs::{read_dir, File},
io::BufWriter,
io::{BufWriter, Read},
};
fn random_chars(n: usize) -> String {
@ -340,3 +340,87 @@ fn test_split_invalid_bytes_size() {
}
}
}
fn file_read(at: &AtPath, filename: &str) -> String {
let mut s = String::new();
at.open(filename).read_to_string(&mut s).unwrap();
s
}
// TODO Use char::from_digit() in Rust v1.51.0 or later.
fn char_from_digit(n: usize) -> char {
(b'a' + n as u8) as char
}
/// Test for the default suffix length behavior: dynamically increasing size.
#[test]
fn test_alphabetic_dynamic_suffix_length() {
let (at, mut ucmd) = at_and_ucmd!();
// Split into chunks of one byte each.
//
// The input file has (26^2) - 26 + 1 = 651 bytes. This is just
// enough to force `split` to dynamically increase the length of
// the filename for the very last chunk.
//
// We expect the output files to be named
//
// xaa, xab, xac, ..., xyx, xyy, xyz, xzaaa
//
ucmd.args(&["-b", "1", "sixhundredfiftyonebytes.txt"])
.succeeds();
for i in 0..25 {
for j in 0..26 {
let filename = format!("x{}{}", char_from_digit(i), char_from_digit(j),);
let contents = file_read(&at, &filename);
assert_eq!(contents, "a");
}
}
assert_eq!(file_read(&at, "xzaaa"), "a");
}
/// Test for the default suffix length behavior: dynamically increasing size.
#[test]
fn test_numeric_dynamic_suffix_length() {
let (at, mut ucmd) = at_and_ucmd!();
// Split into chunks of one byte each, use numbers instead of
// letters as file suffixes.
//
// The input file has (10^2) - 10 + 1 = 91 bytes. This is just
// enough to force `split` to dynamically increase the length of
// the filename for the very last chunk.
//
// x00, x01, x02, ..., x87, x88, x89, x9000
//
ucmd.args(&["-d", "-b", "1", "ninetyonebytes.txt"])
.succeeds();
for i in 0..90 {
let filename = format!("x{:02}", i);
let contents = file_read(&at, &filename);
assert_eq!(contents, "a");
}
assert_eq!(file_read(&at, "x9000"), "a");
}
#[test]
fn test_suffixes_exhausted() {
new_ucmd!()
.args(&["-b", "1", "-a", "1", "asciilowercase.txt"])
.fails()
.stderr_only("split: output file suffixes exhausted");
}
#[test]
fn test_verbose() {
new_ucmd!()
.args(&["-b", "5", "--verbose", "asciilowercase.txt"])
.succeeds()
.stdout_only(
"creating file 'xaa'
creating file 'xab'
creating file 'xac'
creating file 'xad'
creating file 'xae'
creating file 'xaf'
",
);
}

View file

@ -63,9 +63,7 @@ fn test_tee_append() {
fn test_tee_no_more_writeable_1() {
// equals to 'tee /dev/full out2 <multi_read' call
let (at, mut ucmd) = at_and_ucmd!();
let content = (1..=10)
.map(|x| format!("{}\n", x.to_string()))
.collect::<String>();
let content = (1..=10).map(|x| format!("{}\n", x)).collect::<String>();
let file_out = "tee_file_out";
ucmd.arg("/dev/full")
@ -85,9 +83,7 @@ fn test_tee_no_more_writeable_2() {
// but currently there is no way to redirect stdout to /dev/full
// so this test is disabled
let (_at, mut ucmd) = at_and_ucmd!();
let _content = (1..=10)
.map(|x| format!("{}\n", x.to_string()))
.collect::<String>();
let _content = (1..=10).map(|x| format!("{}\n", x)).collect::<String>();
let file_out_a = "tee_file_out_a";
let file_out_b = "tee_file_out_b";

View file

@ -1230,14 +1230,7 @@ pub fn check_coreutil_version(
.output()
{
Ok(s) => s,
Err(e) => {
return Err(format!(
"{}: '{}' {}",
UUTILS_WARNING,
util_name,
e.to_string()
))
}
Err(e) => return Err(format!("{}: '{}' {}", UUTILS_WARNING, util_name, e)),
};
std::str::from_utf8(&version_check.stdout).unwrap()
.split('\n')
@ -1247,7 +1240,7 @@ pub fn check_coreutil_version(
|| Err(format!("{}: unexpected output format for reference coreutil: '{} --version'", UUTILS_WARNING, util_name)),
|s| {
if s.contains(&format!("(GNU coreutils) {}", version_expected)) {
Ok(format!("{}: {}", UUTILS_INFO, s.to_string()))
Ok(format!("{}: {}", UUTILS_INFO, s))
} else if s.contains("(GNU coreutils)") {
let version_found = parse_coreutil_version(s);
let version_expected = version_expected.parse::<f32>().unwrap_or_default();

View file

@ -0,0 +1,2 @@
b d
a c f

View file

@ -0,0 +1,2 @@
b
a c

View file

@ -0,0 +1,2 @@
d
a f

BIN
tests/fixtures/join/non-unicode.expected vendored Normal file

Binary file not shown.

BIN
tests/fixtures/join/non-unicode_1.bin vendored Normal file

Binary file not shown.

BIN
tests/fixtures/join/non-unicode_2.bin vendored Normal file

Binary file not shown.

BIN
tests/fixtures/join/z.expected vendored Normal file

Binary file not shown.

View file

@ -0,0 +1 @@
abcdefghijklmnopqrstuvwxyz

View file

@ -0,0 +1 @@
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

View file

@ -0,0 +1 @@
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa