uniq: pass remaining GNU tests (#5994)

This commit is contained in:
Yury Zhytkou
2024-02-25 09:45:37 +01:00
committed by GitHub
parent 5a2e0c700e
commit 17174ab986
6 changed files with 550 additions and 158 deletions
+372 -118
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -25,6 +25,7 @@ pub use crate::mods::error;
pub use crate::mods::line_ending;
pub use crate::mods::os;
pub use crate::mods::panic;
pub use crate::mods::posix;
// * string parsing modules
pub use crate::parser::parse_glob;
+1
View File
@@ -9,3 +9,4 @@ pub mod error;
pub mod line_ending;
pub mod os;
pub mod panic;
pub mod posix;
+52
View File
@@ -0,0 +1,52 @@
// This file is part of the uutils coreutils package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore (vars)
//! Iterate over lines, including the line ending character(s).
//!
//! This module provides the [`posix_version`] function, that returns
//! Some(usize) if the `_POSIX2_VERSION` environment variable is defined
//! and has value that can be parsed.
//! Otherwise returns None, so the calling utility would assume default behavior.
//!
//! NOTE: GNU (as of v9.4) recognizes three distinct values for POSIX version:
//! '199209' for POSIX 1003.2-1992, which would define Obsolete mode
//! '200112' for POSIX 1003.1-2001, which is the minimum version for Traditional mode
//! '200809' for POSIX 1003.1-2008, which is the minimum version for Modern mode
//!
//! Utilities that rely on this module:
//! `sort` (TBD)
//! `tail` (TBD)
//! `touch` (TBD)
//! `uniq`
//!
use std::env;
pub const OBSOLETE: usize = 199209;
pub const TRADITIONAL: usize = 200112;
pub const MODERN: usize = 200809;
pub fn posix_version() -> Option<usize> {
env::var("_POSIX2_VERSION")
.ok()
.and_then(|v| v.parse::<usize>().ok())
}
#[cfg(test)]
mod tests {
use crate::posix::*;
#[test]
fn test_posix_version() {
// default
assert_eq!(posix_version(), None);
// set specific version
env::set_var("_POSIX2_VERSION", OBSOLETE.to_string());
assert_eq!(posix_version(), Some(OBSOLETE));
env::set_var("_POSIX2_VERSION", TRADITIONAL.to_string());
assert_eq!(posix_version(), Some(TRADITIONAL));
env::set_var("_POSIX2_VERSION", MODERN.to_string());
assert_eq!(posix_version(), Some(MODERN));
}
}
+122 -40
View File
@@ -2,10 +2,10 @@
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
use std::io::Write;
// spell-checker:ignore nabcd
// spell-checker:ignore nabcd badoption schar
use crate::common::util::TestScenario;
use uucore::posix::OBSOLETE;
static INPUT: &str = "sorted.txt";
static OUTPUT: &str = "sorted-output.txt";
@@ -118,10 +118,10 @@ fn test_stdin_skip_21_fields_obsolete() {
#[test]
fn test_stdin_skip_invalid_fields_obsolete() {
new_ucmd!()
.args(&["-5deadbeef"])
.args(&["-5q"])
.run()
.failure()
.stderr_only("uniq: Invalid argument for skip-fields: 5deadbeef\n");
.stderr_contains("error: unexpected argument '-q' found\n");
}
#[test]
@@ -138,8 +138,7 @@ fn test_all_repeated_followed_by_filename() {
let filename = "test.txt";
let (at, mut ucmd) = at_and_ucmd!();
let mut file = at.make_file(filename);
file.write_all(b"a\na\n").unwrap();
at.write(filename, "a\na\n");
ucmd.args(&["--all-repeated", filename])
.run()
@@ -202,14 +201,13 @@ fn test_stdin_zero_terminated() {
}
#[test]
fn test_invalid_utf8() {
fn test_gnu_locale_fr_schar() {
new_ucmd!()
.arg("not-utf8-sequence.txt")
.args(&["-f1", "locale-fr-schar.txt"])
.env("LC_ALL", "C")
.run()
.failure()
.stderr_only(
"uniq: failed to convert line to utf8: invalid utf-8 sequence of 1 bytes from index 0\n",
);
.success()
.stdout_is_fixture_bytes("locale-fr-schar.txt");
}
#[test]
@@ -226,8 +224,7 @@ fn test_group_followed_by_filename() {
let filename = "test.txt";
let (at, mut ucmd) = at_and_ucmd!();
let mut file = at.make_file(filename);
file.write_all(b"a\na\n").unwrap();
at.write(filename, "a\na\n");
ucmd.args(&["--group", filename])
.run()
@@ -521,23 +518,23 @@ fn gnu_tests() {
stderr: None,
exit: None,
},
// // Obsolete syntax for "-s 1"
// TestCase {
// name: "obs-plus40",
// args: &["+1"],
// input: "aaa\naaa\n",
// stdout: Some("aaa\n"),
// stderr: None,
// exit: None,
// },
// TestCase {
// name: "obs-plus41",
// args: &["+1"],
// input: "baa\naaa\n",
// stdout: Some("baa\n"),
// stderr: None,
// exit: None,
// },
// Obsolete syntax for "-s 1"
TestCase {
name: "obs-plus40",
args: &["+1"],
input: "aaa\naaa\n",
stdout: Some("aaa\n"),
stderr: None,
exit: None,
},
TestCase {
name: "obs-plus41",
args: &["+1"],
input: "baa\naaa\n",
stdout: Some("baa\n"),
stderr: None,
exit: None,
},
TestCase {
name: "42",
args: &["-s", "1"],
@@ -554,7 +551,6 @@ fn gnu_tests() {
stderr: None,
exit: None,
},
/*
// Obsolete syntax for "-s 1"
TestCase {
name: "obs-plus44",
@@ -572,7 +568,6 @@ fn gnu_tests() {
stderr: None,
exit: None,
},
*/
TestCase {
name: "50",
args: &["-f", "1", "-s", "1"],
@@ -757,17 +752,14 @@ fn gnu_tests() {
stderr: None,
exit: None,
},
/*
Disable as it fails too often. See:
https://github.com/uutils/coreutils/issues/3509
TestCase {
name: "112",
args: &["-D", "-c"],
input: "a a\na b\n",
stdout: Some(""),
stderr: Some("uniq: printing all duplicated lines and repeat counts is meaningless"),
stderr: Some("uniq: printing all duplicated lines and repeat counts is meaningless\nTry 'uniq --help' for more information.\n"),
exit: Some(1),
},*/
},
TestCase {
name: "113",
args: &["--all-repeated=separate"],
@@ -816,6 +808,14 @@ fn gnu_tests() {
stderr: None,
exit: None,
},
TestCase {
name: "119",
args: &["--all-repeated=badoption"],
input: "a a\na b\n",
stdout: Some(""),
stderr: Some("uniq: invalid argument 'badoption' for '--all-repeated'\nValid arguments are:\n - 'none'\n - 'prepend'\n - 'separate'\nTry 'uniq --help' for more information.\n"),
exit: Some(1),
},
// \x08 is the backspace char
TestCase {
name: "120",
@@ -825,6 +825,16 @@ fn gnu_tests() {
stderr: None,
exit: None,
},
// u128::MAX = 340282366920938463463374607431768211455
TestCase {
name: "121",
args: &["-d", "-u", "-w340282366920938463463374607431768211456"],
input: "a\na\n\x08",
stdout: Some(""),
stderr: None,
exit: None,
},
// Test 122 is the same as 121, just different big int overflow number
TestCase {
name: "123",
args: &["--zero-terminated"],
@@ -969,16 +979,88 @@ fn gnu_tests() {
stderr: None,
exit: None,
},
TestCase {
name: "141",
args: &["--group", "-c"],
input: "",
stdout: Some(""),
stderr: Some("uniq: --group is mutually exclusive with -c/-d/-D/-u\nTry 'uniq --help' for more information.\n"),
exit: Some(1),
},
TestCase {
name: "142",
args: &["--group", "-d"],
input: "",
stdout: Some(""),
stderr: Some("uniq: --group is mutually exclusive with -c/-d/-D/-u\nTry 'uniq --help' for more information.\n"),
exit: Some(1),
},
TestCase {
name: "143",
args: &["--group", "-u"],
input: "",
stdout: Some(""),
stderr: Some("uniq: --group is mutually exclusive with -c/-d/-D/-u\nTry 'uniq --help' for more information.\n"),
exit: Some(1),
},
TestCase {
name: "144",
args: &["--group", "-D"],
input: "",
stdout: Some(""),
stderr: Some("uniq: --group is mutually exclusive with -c/-d/-D/-u\nTry 'uniq --help' for more information.\n"),
exit: Some(1),
},
TestCase {
name: "145",
args: &["--group=badoption"],
input: "",
stdout: Some(""),
stderr: Some("uniq: invalid argument 'badoption' for '--group'\nValid arguments are:\n - 'prepend'\n - 'append'\n - 'separate'\n - 'both'\nTry 'uniq --help' for more information.\n"),
exit: Some(1),
},
];
// run regular version of tests with regular file as input
for case in cases {
// prep input file
let (at, mut ucmd) = at_and_ucmd!();
at.write("input-file", case.input);
// first - run a version of tests with regular file as input
eprintln!("Test {}", case.name);
let result = new_ucmd!().args(case.args).run_piped_stdin(case.input);
// set environment variable for obsolete skip char option tests
if case.name.starts_with("obs-plus") {
ucmd.env("_POSIX2_VERSION", OBSOLETE.to_string());
}
let result = ucmd.args(case.args).arg("input-file").run();
if let Some(stdout) = case.stdout {
result.stdout_is(stdout);
}
if let Some(stderr) = case.stderr {
result.stderr_contains(stderr);
result.stderr_is(stderr);
}
if let Some(exit) = case.exit {
result.code_is(exit);
}
// then - ".stdin" version of tests with input piped in
// NOTE: GNU has another variant for stdin redirect from a file
// as in `uniq < input-file`
// For now we treat it as equivalent of piped in stdin variant
// as in `cat input-file | uniq`
eprintln!("Test {}.stdin", case.name);
// set environment variable for obsolete skip char option tests
let mut ucmd = new_ucmd!();
if case.name.starts_with("obs-plus") {
ucmd.env("_POSIX2_VERSION", OBSOLETE.to_string());
}
let result = ucmd.args(case.args).run_piped_stdin(case.input);
if let Some(stdout) = case.stdout {
result.stdout_is(stdout);
}
if let Some(stderr) = case.stderr {
result.stderr_is(stderr);
}
if let Some(exit) = case.exit {
result.code_is(exit);
+2
View File
@@ -0,0 +1,2 @@
y z
  y z