Skip to content

Commit 5a2e0c7

Browse files
authored
Merge pull request #5990 from BenWiederhake/dev-shuf-head-null
shuf: Do not read input when -n0 is given
2 parents 208b2db + a29f68b commit 5a2e0c7

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

src/uu/shuf/src/shuf.rs

+10
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
102102
},
103103
};
104104

105+
if options.head_count == 0 {
106+
// Do not attempt to read the random source or the input file.
107+
// However, we must touch the output file, if given:
108+
if let Some(s) = options.output {
109+
File::create(&s[..])
110+
.map_err_context(|| format!("failed to open {} for writing", s.quote()))?;
111+
}
112+
return Ok(());
113+
}
114+
105115
match mode {
106116
Mode::Echo(args) => {
107117
let mut evec = args.iter().map(String::as_bytes).collect::<Vec<_>>();

tests/by-util/test_shuf.rs

+75
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
//
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
5+
6+
// spell-checker:ignore (ToDO) unwritable
57
use crate::common::util::TestScenario;
68

79
#[test]
@@ -199,6 +201,79 @@ fn test_head_count() {
199201
);
200202
}
201203

204+
#[test]
205+
fn test_zero_head_count_pipe() {
206+
let result = new_ucmd!().arg("-n0").pipe_in(vec![]).succeeds();
207+
// Output must be completely empty, not even a newline!
208+
result.no_output();
209+
}
210+
211+
#[test]
212+
fn test_zero_head_count_pipe_explicit() {
213+
let result = new_ucmd!().arg("-n0").arg("-").pipe_in(vec![]).succeeds();
214+
result.no_output();
215+
}
216+
217+
#[test]
218+
fn test_zero_head_count_file_unreadable() {
219+
new_ucmd!()
220+
.arg("-n0")
221+
.arg("/invalid/unreadable")
222+
.pipe_in(vec![])
223+
.succeeds()
224+
.no_output();
225+
}
226+
227+
#[test]
228+
fn test_zero_head_count_file_touch_output_negative() {
229+
new_ucmd!()
230+
.arg("-n0")
231+
.arg("-o")
232+
.arg("/invalid/unwritable")
233+
.pipe_in(vec![])
234+
.fails()
235+
.stderr_contains("failed to open '/invalid/unwritable' for writing:");
236+
}
237+
238+
#[test]
239+
fn test_zero_head_count_file_touch_output_positive_new() {
240+
let (at, mut ucmd) = at_and_ucmd!();
241+
ucmd.args(&["-n0", "-o", "file"]).succeeds().no_output();
242+
assert_eq!(
243+
at.read_bytes("file"),
244+
Vec::new(),
245+
"Output file must exist and be completely empty"
246+
);
247+
}
248+
249+
#[test]
250+
fn test_zero_head_count_file_touch_output_positive_existing() {
251+
let (at, mut ucmd) = at_and_ucmd!();
252+
at.touch("file");
253+
ucmd.args(&["-n0", "-o", "file"]).succeeds().no_output();
254+
assert_eq!(
255+
at.read_bytes("file"),
256+
Vec::new(),
257+
"Output file must exist and be completely empty"
258+
);
259+
}
260+
261+
#[test]
262+
fn test_zero_head_count_echo() {
263+
new_ucmd!()
264+
.arg("-n0")
265+
.arg("-e")
266+
.arg("hello")
267+
.pipe_in(vec![])
268+
.succeeds()
269+
.no_output();
270+
}
271+
272+
#[test]
273+
fn test_zero_head_count_range() {
274+
new_ucmd!().arg("-n0").arg("-i4-8").succeeds().no_output();
275+
}
276+
202277
#[test]
203278
fn test_head_count_multi_big_then_small() {
204279
let repeat_limit = 5;

0 commit comments

Comments
 (0)