Skip to content

Commit 1873f00

Browse files
committed
numfmt: buffer output in non-abort invalid modes and re-enable GNU tests
Buffer formatted output so that --invalid=fail does not duplicate lines on error, and --invalid=abort streams directly for partial output. Fixes GNU numfmt.pl test: field-3. Re-enables the full numfmt.pl test suite by removing the skip list added earlier in the stack.
1 parent b91bbf6 commit 1873f00

4 files changed

Lines changed: 33 additions & 29 deletions

File tree

src/uu/numfmt/src/format.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ fn split_bytes<'a>(input: &'a [u8], delim: &'a [u8]) -> impl Iterator<Item = &'a
599599
})
600600
}
601601

602-
pub fn write_formatted_with_delimiter<W: std::io::Write>(
602+
pub fn write_formatted_with_delimiter<W: std::io::Write + ?Sized>(
603603
writer: &mut W,
604604
input: &[u8],
605605
options: &NumfmtOptions,
@@ -635,7 +635,7 @@ pub fn write_formatted_with_delimiter<W: std::io::Write>(
635635
Ok(())
636636
}
637637

638-
pub fn write_formatted_with_whitespace<W: std::io::Write>(
638+
pub fn write_formatted_with_whitespace<W: std::io::Write + ?Sized>(
639639
writer: &mut W,
640640
s: &str,
641641
options: &NumfmtOptions,

src/uu/numfmt/src/numfmt.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use std::str::FromStr;
2020
use units::{IEC_BASES, SI_BASES};
2121
use uucore::display::Quotable;
2222
use uucore::error::UResult;
23+
use uucore::util_name;
2324

2425
use uucore::i18n::decimal::locale_grouping_separator;
2526
use uucore::parser::shortcut_value_parser::ShortcutValueParser;
@@ -94,15 +95,25 @@ fn write_line<W: std::io::Write>(
9495
Some(i) => &input_line[..i],
9596
None => input_line,
9697
};
98+
let buffer_output = !matches!(options.invalid, InvalidModes::Abort);
9799
let mut formatted_line = Vec::new();
98-
let handled_line = if options.delimiter.is_some() {
99-
write_formatted_with_delimiter(&mut formatted_line, line, options, eol)
100-
} else {
101-
// Whitespace mode requires valid UTF-8
102-
match std::str::from_utf8(line) {
103-
Ok(s) => write_formatted_with_whitespace(&mut formatted_line, s, options, eol),
104-
Err(_) => {
105-
Err(translate!("numfmt-error-invalid-number", "input" => escape_line(line).quote()))
100+
let handled_line = {
101+
let output: &mut dyn std::io::Write = if buffer_output {
102+
&mut formatted_line
103+
} else {
104+
writer
105+
};
106+
107+
if options.delimiter.is_some() {
108+
write_formatted_with_delimiter(output, line, options, eol)
109+
} else {
110+
// Whitespace mode requires valid UTF-8
111+
match std::str::from_utf8(line) {
112+
Ok(s) => write_formatted_with_whitespace(output, s, options, eol),
113+
Err(_) => Err(translate!(
114+
"numfmt-error-invalid-number",
115+
"input" => escape_line(line).quote()
116+
)),
106117
}
107118
}
108119
};
@@ -128,7 +139,9 @@ fn write_line<W: std::io::Write>(
128139
return Ok(true);
129140
}
130141

131-
writer.write_all(&formatted_line)?;
142+
if buffer_output {
143+
writer.write_all(&formatted_line)?;
144+
}
132145
Ok(false)
133146
}
134147

tests/by-util/test_numfmt.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,6 +1261,15 @@ fn test_invalid_fail_with_fields_does_not_duplicate_output() {
12611261
.stderr_is("numfmt: invalid number: 'Foo'\n");
12621262
}
12631263

1264+
#[test]
1265+
fn test_abort_with_fields_preserves_partial_output() {
1266+
new_ucmd!()
1267+
.args(&["--field=3", "--from=auto", "Hello 40M World 90G"])
1268+
.fails_with_code(2)
1269+
.stdout_is("Hello 40M ")
1270+
.stderr_is("numfmt: invalid number: 'World'\n");
1271+
}
1272+
12641273
#[test]
12651274
fn test_rejects_malformed_number_forms() {
12661275
new_ucmd!()

util/build-gnu.sh

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -192,24 +192,6 @@ sed -i "s|--coreutils-prog=||g" tests/misc/coreutils.sh
192192
# Use the system coreutils where the test fails due to error in a util that is not the one being tested
193193
sed -i "s|grep '^#define HAVE_CAP 1' \$CONFIG_HEADER > /dev/null|true|" tests/ls/capability.sh
194194

195-
# Keep GNU numfmt coverage focused on the behavior we currently support.
196-
sed -i '/# uutils-numfmt-adjustments start/,/# uutils-numfmt-adjustments end/d' tests/numfmt/numfmt.pl
197-
sed -i '/push @Tests, @Locale_Tests if $locale ne '\''C'\'';/a\
198-
# uutils-numfmt-adjustments start\
199-
my %skip_uutils_numfmt_tests = map { $_ => 1 } qw(\
200-
unit-sep-22-fail grp-1 grp-2 delim-7 field-1\
201-
field-range-err-1 field-range-err-2 field-range-err-3 field-range-err-4\
202-
field-range-err-6 field-range-err-7 field-range-err-8 field-range-err-9\
203-
field-range-err-10 field-range-err-11 field-range-err-12 field-range-err-13\
204-
strtod-6 strtod-6.1 leading-4 debug-2\
205-
devdebug-1 devdebug-2 devdebug-3 devdebug-4 devdebug-5 devdebug-6\
206-
devdebug-7 devdebug-9 devdebug-10 devdebug-11\
207-
help-1 fmt-err-9 fmt-err-11 fmt-15\
208-
ign-err-5 ign-err-m2.2 ign-err-m3.1\
209-
);\
210-
@Tests = grep { !$skip_uutils_numfmt_tests{$_->[0]} } @Tests;\
211-
# uutils-numfmt-adjustments end' tests/numfmt/numfmt.pl
212-
213195
# our messages are better
214196
sed -i "s|cannot stat 'symlink': Permission denied|not writing through dangling symlink 'symlink'|" tests/cp/fail-perm.sh
215197
sed -i "s|cp: target directory 'symlink': Permission denied|cp: 'symlink' is not a directory|" tests/cp/fail-perm.sh

0 commit comments

Comments
 (0)