Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/uu/uniq/src/uniq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ pub fn uu_app() -> Command {
.num_args(0..=1)
.default_missing_value("none")
.require_equals(true)
// GNU accepts a repeated -D/--all-repeated and uses the last one.
// Let the final occurrence select the delimiter method.
.overrides_with(options::ALL_REPEATED),
)
.arg(
Expand Down
50 changes: 26 additions & 24 deletions tests/by-util/test_cat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,55 +649,57 @@
);
}

/// Test derived from the following GNU test in `tests/cat/cat-self.sh`:
/// Test that cat handles self-referential input gracefully.
///
/// `cat fxy2 fy 1<>fxy2`
// TODO: make this work on windows
#[test]
#[cfg(unix)]
fn test_successful_write_to_read_write_self() {
fn test_cat_rw_self_succeeds() {
let (at, mut ucmd) = at_and_ucmd!();
at.write("fy", "y");
at.write("fxy2", "x");
at.write("extra", "world");
at.write("combined", "hello");

// Open `rw_file` as both stdin and stdout (read/write)
let fxy2_file_path = at.plus("fxy2");
let fxy2_file = OpenOptions::new()
let combined_file_path = at.plus("combined");
let combined_file = OpenOptions::new()
.read(true)
.write(true)
.open(&fxy2_file_path)
.open(&combined_file_path)
.unwrap();
ucmd.args(&["fxy2", "fy"]).set_stdout(fxy2_file).succeeds();
ucmd.args(&["combined", "extra"])
.set_stdout(combined_file)
.succeeds();

// The contents of `fxy2` and `fy` files should be merged
let fxy2_contents = read_to_string(fxy2_file_path).unwrap();
assert_eq!(fxy2_contents, "xy");
// The contents of `combined` and `extra` files should be merged
let combined_contents = read_to_string(combined_file_path).unwrap();
assert_eq!(combined_contents, "helloworld");
}

/// Test derived from the following GNU test in `tests/cat/cat-self.sh`:
/// Test that cat handles self-referential input gracefully.
///
/// `cat fx fx3 1<>fx3`
#[test]
fn test_failed_write_to_read_write_self() {
fn test_cat_rw_self_conflict_fails() {
let (at, mut ucmd) = at_and_ucmd!();
at.write("fx", "g");
at.write("fx3", "bold");
at.write("source", "a");
at.write("dest", "bcde");

Check warning on line 686 in tests/by-util/test_cat.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

WARNING: `cspell`: Unknown word 'bcde' (file:'tests/by-util/test_cat.rs', line:686)

// Open `rw_file` as both stdin and stdout (read/write)
let fx3_file_path = at.plus("fx3");
let fx3_file = OpenOptions::new()
let dest_file_path = at.plus("dest");
let dest_file = OpenOptions::new()
.read(true)
.write(true)
.open(&fx3_file_path)
.open(&dest_file_path)
.unwrap();
ucmd.args(&["fx", "fx3"])
.set_stdout(fx3_file)
ucmd.args(&["source", "dest"])
.set_stdout(dest_file)
.fails_with_code(1)
.stderr_only("cat: fx3: input file is output file\n");
.stderr_only("cat: dest: input file is output file\n");

// The contents of `fx` should have overwritten the beginning of `fx3`
let fx3_contents = read_to_string(fx3_file_path).unwrap();
assert_eq!(fx3_contents, "gold");
// The contents of `source` should have overwritten the beginning of `dest`
let dest_contents = read_to_string(dest_file_path).unwrap();
assert_eq!(dest_contents, "acde");

Check warning on line 702 in tests/by-util/test_cat.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

WARNING: `cspell`: Unknown word 'acde' (file:'tests/by-util/test_cat.rs', line:702)
}

#[test]
Expand Down
20 changes: 10 additions & 10 deletions tests/by-util/test_cksum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2239,8 +2239,8 @@ fn test_check_incorrectly_formatted_checksum_keeps_processing_hex() {
.stderr_contains("cksum: WARNING: 1 line is improperly formatted");
}

/// This module reimplements the cksum-base64.pl GNU test.
mod gnu_cksum_base64 {
/// Tests for cksum with base64 output encoding.
mod cksum_base64_encoding {
use super::*;
use uutests::util::log_info;

Expand Down Expand Up @@ -2285,7 +2285,7 @@ mod gnu_cksum_base64 {
}

#[test]
fn test_generating() {
fn test_cksum_base64_generating() {
// Ensure that each algorithm works with `--base64`.
let scene = make_scene();

Expand All @@ -2303,7 +2303,7 @@ mod gnu_cksum_base64 {
}

#[test]
fn test_chk() {
fn test_cksum_base64_verify() {
// For each algorithm that accepts `--check`,
// ensure that it works with base64 digests.
let scene = make_scene();
Expand Down Expand Up @@ -2335,7 +2335,7 @@ mod gnu_cksum_base64 {
}

#[test]
fn test_chk_eq1() {
fn test_cksum_base64_verify_truncated_eq1() {
// For digests ending with '=', ensure `--check` fails if '=' is removed.
let scene = make_scene();

Expand All @@ -2361,7 +2361,7 @@ mod gnu_cksum_base64 {
}

#[test]
fn test_chk_eq2() {
fn test_cksum_base64_verify_truncated_eq2() {
// For digests ending with '==',
// ensure `--check` fails if '==' is removed.
let scene = make_scene();
Expand All @@ -2386,8 +2386,8 @@ mod gnu_cksum_base64 {
}
}

/// This module reimplements the cksum-base64-untagged.sh GNU test.
mod gnu_cksum_base64_untagged {
/// Tests for cksum with base64 output encoding (untagged mode).
mod cksum_base64_untagged_encoding {
use super::*;

macro_rules! decl_sha_test {
Expand Down Expand Up @@ -2499,8 +2499,8 @@ mod gnu_cksum_base64_untagged {
decl_blake_test!(blake2b_504, 504);
decl_blake_test!(blake2b_512, 512);
}
/// This module reimplements the cksum-c.sh GNU test.
mod gnu_cksum_c {
/// Tests for cksum check mode (-c/--check).
mod cksum_check_mode {
use super::*;

const INVALID_SUM: &str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaafdb57c725157cb40b5aee8d937b8351477e";
Expand Down
4 changes: 2 additions & 2 deletions tests/by-util/test_comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ fn test_both_inputs_out_of_order_but_identical() {
fn test_comm_arg_error() {
let scene = TestScenario::new(util_name!());

// Test extra argument error case from GNU test
// Test extra argument error case
scene
.ucmd()
.args(&["a", "b", "no-such"])
Expand All @@ -588,7 +588,7 @@ fn test_comm_arg_error() {
.stderr_contains("error: unexpected argument 'no-such' found")
.stderr_contains("Usage: comm [OPTION]... FILE1 FILE2")
.stderr_contains("For more information, try '--help'.");
// Test extra argument error case from GNU test
// Test extra argument error case
scene
.ucmd()
.args(&["a"])
Expand Down
50 changes: 25 additions & 25 deletions tests/by-util/test_date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2489,41 +2489,41 @@ fn test_date_write_error_dev_full() {
.stderr_contains("write error");
}

// Tests for GNU test leap-1: leap year overflow in date arithmetic
// Tests for leap year overflow in date arithmetic
#[test]
fn test_date_leap1_leap_year_overflow() {
// GNU test leap-1: Adding years to Feb 29 should overflow to March 1
fn test_date_leap_year_arithmetic_overflow() {
// Adding years to Feb 29 should overflow to March 1
// if target year is not a leap year
new_ucmd!()
.args(&["--date", "02/29/1996 1 year", "+%Y-%m-%d"])
.args(&["--date", "02/29/2000 1 year", "+%Y-%m-%d"])
.succeeds()
.stdout_is("1997-03-01\n");
.stdout_is("2001-03-01\n");

// Additional cases: 2 years
new_ucmd!()
.args(&["--date", "1996-02-29 + 2 years", "+%Y-%m-%d"])
.args(&["--date", "2000-02-29 + 2 years", "+%Y-%m-%d"])
.succeeds()
.stdout_is("1998-03-01\n");
.stdout_is("2002-03-01\n");

// Leap year to leap year should not overflow
new_ucmd!()
.args(&["--date", "1996-02-29 + 4 years", "+%Y-%m-%d"])
.args(&["--date", "2000-02-29 + 4 years", "+%Y-%m-%d"])
.succeeds()
.stdout_is("2000-02-29\n");
.stdout_is("2004-02-29\n");
}

// Tests for GNU test rel-2b: month arithmetic precision
// Tests for month arithmetic precision
#[test]
fn test_date_rel2b_month_arithmetic() {
// GNU test rel-2b: Subtracting months should maintain same day of month
fn test_date_month_subtraction_keeps_day() {
// Subtracting months should maintain same day of month
new_ucmd!()
.args(&[
"--date",
"1997-01-19 08:17:48 +0 7 months ago",
"2003-08-31 12:00:00 +0 7 months ago",
"+%Y-%m-%d %T",
])
.succeeds()
.stdout_contains("1996-06-19");
.stdout_contains("2003-01-31");

// Month overflow: Adding months should overflow to next month if day doesn't exist
new_ucmd!()
Expand All @@ -2532,37 +2532,37 @@ fn test_date_rel2b_month_arithmetic() {
.stdout_is("1996-03-02\n");
}

// Tests for GNU test cross-TZ-mishandled: embedded timezone parsing
// Tests for embedded timezone parsing
#[test]
fn test_date_cross_tz_mishandled() {
// GNU test cross-TZ-mishandled: Parse date with embedded timezone
fn test_date_embedded_timezone_conversion() {
// Parse date with embedded timezone
// Date should be interpreted in embedded TZ, then displayed in environment TZ
new_ucmd!()
.env("TZ", "PST8")
.env("TZ", "UTC0")
.env("LC_ALL", "C")
.args(&["-d", r#"TZ="EST5" 1970-01-01 00:00"#])
.args(&["-d", r#"TZ="CET-1" 1970-01-01 00:00"#])
.succeeds()
.stdout_contains("Dec 31")
.stdout_contains("21:00:00")
.stdout_contains("23:00:00")
.stdout_contains("1969");
}

// Tests for GNU test invalid-high-bit-set: invalid UTF-8 in date string
// Tests for invalid UTF-8 in date string
#[test]
#[cfg(unix)]
fn test_date_invalid_high_bit_set() {
fn test_date_invalid_utf8_byte_rejected() {
use std::os::unix::ffi::OsStrExt;

// GNU test invalid-high-bit-set: Invalid UTF-8 byte (0xb0) should produce
// Invalid UTF-8 byte (0xb0) should produce
// GNU-compatible error message with octal escape sequence
let invalid_bytes = b"\xb0";
let invalid_bytes = b"\xe0";
let invalid_arg = std::ffi::OsStr::from_bytes(invalid_bytes);

new_ucmd!()
.args(&[std::ffi::OsStr::new("-d"), invalid_arg])
.fails()
.code_is(1)
.stderr_contains("invalid date '\\260'");
.stderr_contains("invalid date '\\340'");
}

// Tests for GNU format modifiers
Expand Down
6 changes: 3 additions & 3 deletions tests/by-util/test_du.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1512,7 +1512,7 @@ fn test_du_invalid_threshold() {

#[test]
fn test_du_threshold_error_handling() {
// Test missing threshold value - the specific case from GNU test
// Test missing threshold value
new_ucmd!()
.arg("--threshold")
.fails()
Expand Down Expand Up @@ -2333,7 +2333,7 @@ fn test_du_symlink_depth_tracking() {
#[test]
#[cfg(target_os = "linux")]
fn test_du_long_path_from_unreadable() {
// Test the specific scenario from GNU's long-from-unreadable.sh test
// Test du behavior with unreadable directories
// This verifies that du can handle very long paths when the current directory is unreadable
use std::env;
use std::fs;
Expand All @@ -2342,7 +2342,7 @@ fn test_du_long_path_from_unreadable() {
let ts = TestScenario::new(util_name!());
let at = &ts.fixtures;

// Create a deep hierarchy similar to the GNU test
// Create a deep hierarchy
// Use a more reasonable depth for unit tests
let dir_name = "x".repeat(200);
let mut current_path = String::new();
Expand Down
12 changes: 6 additions & 6 deletions tests/by-util/test_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,21 +632,21 @@ fn test_split_string_into_args_debug_output_whitespace_handling() {
}

// FixMe: This test fails on MACOS:
// thread 'test_env::test_gnu_e20' panicked at 'assertion failed: `(left == right)`
// left: `"A=B C=D\n__CF_USER_TEXT_ENCODING=0x1F5:0x0:0x0\n"`,
// right: `"A=B C=D\n"`', tests/by-util/test_env.rs:369:5
// thread 'test_env::test_env_split_quoted_with_backslash_space' panicked at 'assertion failed: `(left == right)`
// left: `"X=Y Z=W\n__CF_USER_TEXT_ENCODING=0x1F5:0x0:0x0\n"`,
// right: `"X=Y Z=W\n"`', tests/by-util/test_env.rs:369:5
#[cfg(not(target_os = "macos"))]
#[test]
fn test_gnu_e20() {
fn test_env_split_quoted_with_backslash_space() {
let scene = TestScenario::new(util_name!());

let env_bin = String::from(uutests::util::get_tests_binary()) + " " + util_name!();
let input = [
String::from("-i"),
String::from(r#"-SA="B\_C=D" "#) + env_bin.escape_default().to_string().as_str() + "",
String::from(r#"-SX="Y\_Z=W" "#) + env_bin.escape_default().to_string().as_str() + "",
];

let mut output = "A=B C=D\n".to_string();
let mut output = "X=Y Z=W\n".to_string();

// Workaround for the test to pass when coverage is being run.
// If enabled, the binary called by env_bin will most probably be
Expand Down
Loading
Loading