Skip to content

Commit 70d04ec

Browse files
committed
Head: ensure stdin input stream is correct on exit
Fix issue uutils#7028 Head tool now ensures that stdin is set to the last character that was output by the tool. This ensures that if any subsequent tools are run from the same input stream they will start at the correct point in the stream.
1 parent 76ad604 commit 70d04ec

5 files changed

+175
-146
lines changed

tests/by-util/test_head.rs

+112-146
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,6 @@
77
// spell-checker:ignore (words) seekable
88

99
use crate::common::util::TestScenario;
10-
#[cfg(all(
11-
not(target_os = "windows"),
12-
not(target_os = "macos"),
13-
not(target_os = "android"),
14-
not(target_os = "freebsd"),
15-
not(target_os = "openbsd")
16-
))]
17-
use std::io::Read;
1810

1911
static INPUT: &str = "lorem_ipsum.txt";
2012

@@ -408,36 +400,36 @@ fn test_all_but_last_bytes_large_file_piped() {
408400
let fixtures = &scene.fixtures;
409401

410402
// First, create all our fixtures.
411-
let seq_20000_file_name = "seq_20000";
412-
let seq_19000_file_name = "seq_19000";
413-
let seq_19001_20000_file_name = "seq_19001_20000";
403+
let seq_30000_file_name = "seq_30000";
404+
let seq_29000_file_name = "seq_29000";
405+
let seq_29001_30000_file_name = "seq_29001_30000";
414406
scene
415407
.cmd("seq")
416-
.arg("20000")
417-
.set_stdout(fixtures.make_file(seq_20000_file_name))
408+
.arg("30000")
409+
.set_stdout(fixtures.make_file(seq_30000_file_name))
418410
.succeeds();
419411
scene
420412
.cmd("seq")
421-
.arg("19000")
422-
.set_stdout(fixtures.make_file(seq_19000_file_name))
413+
.arg("29000")
414+
.set_stdout(fixtures.make_file(seq_29000_file_name))
423415
.succeeds();
424416
scene
425417
.cmd("seq")
426-
.args(&["19001", "20000"])
427-
.set_stdout(fixtures.make_file(seq_19001_20000_file_name))
418+
.args(&["29001", "30000"])
419+
.set_stdout(fixtures.make_file(seq_29001_30000_file_name))
428420
.succeeds();
429421

430-
let seq_19001_20000_file_length = fixtures
431-
.open(seq_19001_20000_file_name)
422+
let seq_29001_30000_file_length = fixtures
423+
.open(seq_29001_30000_file_name)
432424
.metadata()
433425
.unwrap()
434426
.len();
435427
scene
436428
.ucmd()
437-
.args(&["-c", &format!("-{}", seq_19001_20000_file_length)])
438-
.pipe_in_fixture(seq_20000_file_name)
429+
.args(&["-c", &format!("-{}", seq_29001_30000_file_length)])
430+
.pipe_in_fixture(seq_30000_file_name)
439431
.succeeds()
440-
.stdout_only_fixture(seq_19000_file_name);
432+
.stdout_only_fixture(seq_29000_file_name);
441433
}
442434

443435
#[test]
@@ -447,12 +439,12 @@ fn test_all_but_last_lines_large_file() {
447439
// than that.
448440
let scene = TestScenario::new(util_name!());
449441
let fixtures = &scene.fixtures;
450-
let seq_20000_file_name = "seq_20000";
442+
let seq_30000_file_name = "seq_30000";
451443
let seq_1000_file_name = "seq_1000";
452444
scene
453445
.cmd("seq")
454-
.arg("20000")
455-
.set_stdout(fixtures.make_file(seq_20000_file_name))
446+
.arg("30000")
447+
.set_stdout(fixtures.make_file(seq_30000_file_name))
456448
.succeeds();
457449
scene
458450
.cmd("seq")
@@ -463,19 +455,19 @@ fn test_all_but_last_lines_large_file() {
463455
// Now run our tests.
464456
scene
465457
.ucmd()
466-
.args(&["-n", "-19000", seq_20000_file_name])
458+
.args(&["-n", "-29000", seq_30000_file_name])
467459
.succeeds()
468460
.stdout_only_fixture("seq_1000");
469461

470462
scene
471463
.ucmd()
472-
.args(&["-n", "-20000", seq_20000_file_name])
464+
.args(&["-n", "-30000", seq_30000_file_name])
473465
.succeeds()
474466
.stdout_only_fixture("emptyfile.txt");
475467

476468
scene
477469
.ucmd()
478-
.args(&["-n", "-20001", seq_20000_file_name])
470+
.args(&["-n", "-30001", seq_30000_file_name])
479471
.succeeds()
480472
.stdout_only_fixture("emptyfile.txt");
481473
}
@@ -503,56 +495,14 @@ fn test_validate_stdin_offset_lines() {
503495
let scene = TestScenario::new(util_name!());
504496
let fixtures = &scene.fixtures;
505497

506-
// Test 1 - Print the first n lines
507-
fixtures.write("f1", "a\nb\nc\n");
508-
let file = fixtures.open("f1");
509-
let mut file_shadow = file.try_clone().unwrap();
510-
scene
511-
.ucmd()
512-
.args(&["-n", "1"])
513-
.set_stdin(file)
514-
.succeeds()
515-
.stdout_only("a\n");
516-
let mut bytes_remaining_in_stdin = vec![];
517-
assert_eq!(
518-
file_shadow
519-
.read_to_end(&mut bytes_remaining_in_stdin)
520-
.unwrap(),
521-
4
522-
);
523-
assert_eq!(
524-
String::from_utf8(bytes_remaining_in_stdin).unwrap(),
525-
"b\nc\n"
526-
);
527-
528-
// Test 2 - Print all-but the last n lines
529-
fixtures.write("f2", "a\nb\nc\n");
530-
let file = fixtures.open("f2");
531-
let mut file_shadow = file.try_clone().unwrap();
532-
scene
533-
.ucmd()
534-
.args(&["-n", "-1"])
535-
.set_stdin(file)
536-
.succeeds()
537-
.stdout_only("a\nb\n");
538-
let mut bytes_remaining_in_stdin = vec![];
539-
assert_eq!(
540-
file_shadow
541-
.read_to_end(&mut bytes_remaining_in_stdin)
542-
.unwrap(),
543-
2
544-
);
545-
assert_eq!(String::from_utf8(bytes_remaining_in_stdin).unwrap(), "c\n");
546-
547-
// Test 3 - Print all but the last n lines, large input file.
548498
// First, create all our fixtures.
549-
let seq_20000_file_name = "seq_20000";
499+
let seq_30000_file_name = "seq_30000";
550500
let seq_1000_file_name = "seq_1000";
551-
let seq_1001_20000_file_name = "seq_1001_20000";
501+
let seq_1001_30000_file_name = "seq_1001_30000";
552502
scene
553503
.cmd("seq")
554-
.arg("20000")
555-
.set_stdout(fixtures.make_file(seq_20000_file_name))
504+
.arg("30000")
505+
.set_stdout(fixtures.make_file(seq_30000_file_name))
556506
.succeeds();
557507
scene
558508
.cmd("seq")
@@ -561,23 +511,54 @@ fn test_validate_stdin_offset_lines() {
561511
.succeeds();
562512
scene
563513
.cmd("seq")
564-
.args(&["1001", "20000"])
565-
.set_stdout(fixtures.make_file(seq_1001_20000_file_name))
514+
.args(&["1001", "30000"])
515+
.set_stdout(fixtures.make_file(seq_1001_30000_file_name))
566516
.succeeds();
567517

568-
let file = fixtures.open(seq_20000_file_name);
518+
// Test 1 - Print the first n lines
519+
let file = fixtures.open("lorem_ipsum.txt");
520+
let file_shadow = file.try_clone().unwrap();
521+
scene
522+
.ucmd()
523+
.args(&["-n", "1"])
524+
.set_stdin(file)
525+
.succeeds()
526+
.stdout_only_fixture("lorem_ipsum_1_line.expected");
527+
scene
528+
.cmd("cat")
529+
.set_stdin(file_shadow)
530+
.succeeds()
531+
.stdout_only_fixture("lorem_ipsum_1_line.remaining");
532+
533+
// Test 2 - Print all-but the last n lines
534+
let file = fixtures.open("lorem_ipsum.txt");
535+
let file_shadow = file.try_clone().unwrap();
536+
scene
537+
.ucmd()
538+
.args(&["-n", "-15"])
539+
.set_stdin(file)
540+
.succeeds()
541+
.stdout_only_fixture("lorem_ipsum_backwards_15_lines.expected");
542+
scene
543+
.cmd("cat")
544+
.set_stdin(file_shadow)
545+
.succeeds()
546+
.stdout_only_fixture("lorem_ipsum_backwards_15_lines.remaining");
547+
548+
// Test 3 - Print all but the last n lines, large input file.
549+
let file = fixtures.open(seq_30000_file_name);
569550
let file_shadow = file.try_clone().unwrap();
570551
scene
571552
.ucmd()
572-
.args(&["-n", "-19000"])
553+
.args(&["-n", "-29000"])
573554
.set_stdin(file)
574555
.succeeds()
575556
.stdout_only_fixture(seq_1000_file_name);
576557
scene
577558
.cmd("cat")
578559
.set_stdin(file_shadow)
579560
.succeeds()
580-
.stdout_only_fixture(seq_1001_20000_file_name);
561+
.stdout_only_fixture(seq_1001_30000_file_name);
581562
}
582563

583564
#[cfg(all(
@@ -604,105 +585,90 @@ fn test_validate_stdin_offset_bytes() {
604585
let scene = TestScenario::new(util_name!());
605586
let fixtures = &scene.fixtures;
606587

588+
// First, create all our fixtures.
589+
let seq_30000_file_name = "seq_30000";
590+
let seq_29000_file_name = "seq_29000";
591+
let seq_29001_30000_file_name = "seq_29001_30000";
592+
scene
593+
.cmd("seq")
594+
.arg("30000")
595+
.set_stdout(fixtures.make_file(seq_30000_file_name))
596+
.succeeds();
597+
scene
598+
.cmd("seq")
599+
.arg("29000")
600+
.set_stdout(fixtures.make_file(seq_29000_file_name))
601+
.succeeds();
602+
scene
603+
.cmd("seq")
604+
.args(&["29001", "30000"])
605+
.set_stdout(fixtures.make_file(seq_29001_30000_file_name))
606+
.succeeds();
607+
607608
// Test 1 - Print the first n bytes
608-
fixtures.write("f1", "abc\ndef\n");
609-
let file = fixtures.open("f1");
610-
let mut file_shadow = file.try_clone().unwrap();
609+
let file = fixtures.open("lorem_ipsum.txt");
610+
let file_shadow = file.try_clone().unwrap();
611611
scene
612612
.ucmd()
613-
.args(&["-c", "2"])
613+
.args(&["-c", "5"])
614614
.set_stdin(file)
615615
.succeeds()
616-
.stdout_only("ab");
617-
let mut bytes_remaining_in_stdin = vec![];
618-
assert_eq!(
619-
file_shadow
620-
.read_to_end(&mut bytes_remaining_in_stdin)
621-
.unwrap(),
622-
6
623-
);
624-
assert_eq!(
625-
String::from_utf8(bytes_remaining_in_stdin).unwrap(),
626-
"c\ndef\n"
627-
);
616+
.stdout_only_fixture("lorem_ipsum_5_chars.expected");
617+
scene
618+
.cmd("cat")
619+
.set_stdin(file_shadow)
620+
.succeeds()
621+
.stdout_only_fixture("lorem_ipsum_5_chars.remaining");
628622

629623
// Test 2 - Print all-but the last n bytes
630-
fixtures.write("f2", "abc\ndef\n");
631-
let file = fixtures.open("f2");
632-
let mut file_shadow = file.try_clone().unwrap();
624+
let file = fixtures.open("lorem_ipsum.txt");
625+
let file_shadow = file.try_clone().unwrap();
633626
scene
634627
.ucmd()
635-
.args(&["-c", "-3"])
628+
.args(&["-c", "-10"])
636629
.set_stdin(file)
637630
.succeeds()
638-
.stdout_only("abc\nd");
639-
let mut bytes_remaining_in_stdin = vec![];
640-
assert_eq!(
641-
file_shadow
642-
.read_to_end(&mut bytes_remaining_in_stdin)
643-
.unwrap(),
644-
3
645-
);
646-
assert_eq!(String::from_utf8(bytes_remaining_in_stdin).unwrap(), "ef\n");
631+
.stdout_only_fixture("lorem_ipsum_backwards_file.expected");
632+
scene
633+
.cmd("cat")
634+
.set_stdin(file_shadow)
635+
.succeeds()
636+
.stdout_only_fixture("lorem_ipsum_backwards_file.remaining");
647637

648638
// Test 3 - Print all-but the last n bytes, n=0 (i.e. print everything)
649-
fixtures.write("f3", "abc\ndef\n");
650-
let file = fixtures.open("f3");
651-
let mut file_shadow = file.try_clone().unwrap();
639+
let file = fixtures.open("lorem_ipsum.txt");
640+
let file_shadow = file.try_clone().unwrap();
652641
scene
653642
.ucmd()
654643
.args(&["-c", "-0"])
655644
.set_stdin(file)
656645
.succeeds()
657-
.stdout_only("abc\ndef\n");
658-
let mut bytes_remaining_in_stdin = vec![];
659-
assert_eq!(
660-
file_shadow
661-
.read_to_end(&mut bytes_remaining_in_stdin)
662-
.unwrap(),
663-
0
664-
);
665-
assert_eq!(String::from_utf8(bytes_remaining_in_stdin).unwrap(), "");
666-
667-
// Test 4 - Print all but the last n bytes, large input file.
668-
// First, create all our fixtures.
669-
let seq_20000_file_name = "seq_20000";
670-
let seq_19000_file_name = "seq_19000";
671-
let seq_19001_20000_file_name = "seq_19001_20000";
672-
scene
673-
.cmd("seq")
674-
.arg("20000")
675-
.set_stdout(fixtures.make_file(seq_20000_file_name))
676-
.succeeds();
646+
.stdout_only_fixture("lorem_ipsum.txt");
677647
scene
678-
.cmd("seq")
679-
.arg("19000")
680-
.set_stdout(fixtures.make_file(seq_19000_file_name))
681-
.succeeds();
682-
scene
683-
.cmd("seq")
684-
.args(&["19001", "20000"])
685-
.set_stdout(fixtures.make_file(seq_19001_20000_file_name))
686-
.succeeds();
648+
.cmd("cat")
649+
.set_stdin(file_shadow)
650+
.succeeds()
651+
.stdout_only_fixture("emptyfile.txt");
687652

688-
let file = fixtures.open(seq_20000_file_name);
653+
// Test 4 - Print all but the last n bytes, large input file.
654+
let file = fixtures.open("seq_30000");
689655
let file_shadow = file.try_clone().unwrap();
690-
let seq_19001_20000_file_length = fixtures
691-
.open(seq_19001_20000_file_name)
656+
let seq_29001_30000_file_length = fixtures
657+
.open(seq_29001_30000_file_name)
692658
.metadata()
693659
.unwrap()
694660
.len();
695661
scene
696662
.ucmd()
697-
.args(&["-c", &format!("-{}", seq_19001_20000_file_length)])
663+
.args(&["-c", &format!("-{}", seq_29001_30000_file_length)])
698664
.set_stdin(file)
699665
.succeeds()
700-
.stdout_only_fixture(seq_19000_file_name);
666+
.stdout_only_fixture(seq_29000_file_name);
701667
scene
702668
.cmd("cat")
703669
.set_stdin(file_shadow)
704670
.succeeds()
705-
.stdout_only_fixture(seq_19001_20000_file_name);
671+
.stdout_only_fixture(seq_29001_30000_file_name);
706672
}
707673

708674
#[cfg(all(

0 commit comments

Comments
 (0)