Files
coreutils/tests/by-util/test_csplit.rs
Chris Dryden a297d26cfa csplit: detect and report write errors (#9855)
* csplit: detect and report write errors

* Add Rust integration tests for csplit write error detection

* csplit: fix doc comment for finish_split
2025-12-31 20:09:39 +01:00

1586 lines
46 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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.
use glob::glob;
use uutests::at_and_ucmd;
use uutests::new_ucmd;
/// Returns a string of numbers with the given range, each on a new line.
/// The upper bound is not included.
fn generate(from: u32, to: u32) -> String {
(from..to).fold(String::new(), |acc, v| format!("{acc}{v}\n"))
}
#[test]
fn test_line_numbers_suppress_matched_final_empty() {
// Repro for #7286
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--suppress-matched", "-", "2", "4", "6"]) // stdin, split at 2/4/6
.pipe_in("1\n2\n3\n4\n5\n6\n")
.succeeds()
.stdout_only("2\n2\n2\n0\n");
// Expect four files: xx00:"1\n", xx01:"3\n", xx02:"5\n", xx03:""
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 4);
assert_eq!(at.read("xx00"), "1\n");
assert_eq!(at.read("xx01"), "3\n");
assert_eq!(at.read("xx02"), "5\n");
assert_eq!(at.read("xx03"), "");
}
#[test]
fn test_line_numbers_suppress_matched_final_empty_elided_with_z() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--suppress-matched", "-z", "-", "2", "4", "6"]) // elide empty
.pipe_in("1\n2\n3\n4\n5\n6\n")
.succeeds()
.stdout_only("2\n2\n2\n");
// Expect three files: xx00:"1\n", xx01:"3\n", xx02:"5\n"
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 3);
assert_eq!(at.read("xx00"), "1\n");
assert_eq!(at.read("xx01"), "3\n");
assert_eq!(at.read("xx02"), "5\n");
}
#[test]
fn test_invalid_arg() {
new_ucmd!().arg("--definitely-invalid").fails_with_code(1);
}
#[test]
fn test_stdin() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["-", "10"])
.pipe_in(generate(1, 51))
.succeeds()
.stdout_only("18\n123\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(10, 51));
}
#[test]
fn test_up_to_line() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "10"])
.succeeds()
.stdout_only("18\n123\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(10, 51));
}
#[test]
fn test_up_to_line_repeat_twice() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "10", "{2}"])
.succeeds()
.stdout_only("18\n30\n30\n63\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 4);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(10, 20));
assert_eq!(at.read("xx02"), generate(20, 30));
assert_eq!(at.read("xx03"), generate(30, 51));
}
#[test]
fn test_up_to_line_sequence() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "10", "25"])
.succeeds()
.stdout_only("18\n45\n78\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 3);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(10, 25));
assert_eq!(at.read("xx02"), generate(25, 51));
}
#[test]
fn test_up_to_line_with_non_ascii_repeat() {
// we use a different error message than GNU
new_ucmd!()
.args(&["numbers50.txt", "10", "{𝟚}"])
.fails()
.stderr_contains("invalid pattern");
}
#[test]
fn test_up_to_match() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/9$/"])
.succeeds()
.stdout_only("16\n125\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 9));
assert_eq!(at.read("xx01"), generate(9, 51));
}
#[test]
fn test_up_to_match_repeat_twice() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/9$/", "{2}"])
.succeeds()
.stdout_only("16\n29\n30\n66\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 4);
assert_eq!(at.read("xx00"), generate(1, 9));
assert_eq!(at.read("xx01"), generate(9, 19));
assert_eq!(at.read("xx02"), generate(19, 29));
assert_eq!(at.read("xx03"), generate(29, 51));
}
#[test]
fn test_up_to_match_sequence() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/9$/", "/5$/"])
.succeeds()
.stdout_only("16\n17\n108\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 3);
assert_eq!(at.read("xx00"), generate(1, 9));
assert_eq!(at.read("xx01"), generate(9, 15));
assert_eq!(at.read("xx02"), generate(15, 51));
}
#[test]
fn test_up_to_match_offset() {
for offset in ["3", "+3"] {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", &format!("/9$/{offset}")])
.succeeds()
.stdout_only("24\n117\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 12));
assert_eq!(at.read("xx01"), generate(12, 51));
at.remove("xx00");
at.remove("xx01");
}
}
#[test]
fn test_up_to_match_offset_repeat_twice() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/9$/+3", "{2}"])
.succeeds()
.stdout_only("24\n30\n30\n57\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 4);
assert_eq!(at.read("xx00"), generate(1, 12));
assert_eq!(at.read("xx01"), generate(12, 22));
assert_eq!(at.read("xx02"), generate(22, 32));
assert_eq!(at.read("xx03"), generate(32, 51));
}
#[test]
fn test_up_to_match_non_ascii_offset() {
// we use a different error message than GNU
new_ucmd!()
.args(&["numbers50.txt", "/9$/𝟚"])
.fails()
.stderr_contains("invalid pattern");
}
#[test]
fn test_up_to_match_negative_offset() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/9$/-3"])
.succeeds()
.stdout_only("10\n131\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 6));
assert_eq!(at.read("xx01"), generate(6, 51));
}
#[test]
fn test_up_to_match_negative_offset_repeat_twice() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/9$/-3", "{2}"])
.succeeds()
.stdout_only("10\n26\n30\n75\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 4);
assert_eq!(at.read("xx00"), generate(1, 6));
assert_eq!(at.read("xx01"), generate(6, 16));
assert_eq!(at.read("xx02"), generate(16, 26));
assert_eq!(at.read("xx03"), generate(26, 51));
}
#[test]
fn test_up_to_match_repeat_always() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/9$/", "{*}"])
.succeeds()
.stdout_only("16\n29\n30\n30\n30\n6\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 6);
assert_eq!(at.read("xx00"), generate(1, 9));
assert_eq!(at.read("xx01"), generate(9, 19));
assert_eq!(at.read("xx02"), generate(19, 29));
assert_eq!(at.read("xx03"), generate(29, 39));
assert_eq!(at.read("xx04"), generate(39, 49));
assert_eq!(at.read("xx05"), generate(49, 51));
}
#[test]
fn test_up_to_match_repeat_over() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/9$/", "{50}"])
.fails()
.stdout_is("16\n29\n30\n30\n30\n6\n")
.stderr_is("csplit: '/9$/': match not found on repetition 5\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/9$/", "{50}", "-k"])
.fails()
.stdout_is("16\n29\n30\n30\n30\n6\n")
.stderr_is("csplit: '/9$/': match not found on repetition 5\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 6);
assert_eq!(at.read("xx00"), generate(1, 9));
assert_eq!(at.read("xx01"), generate(9, 19));
assert_eq!(at.read("xx02"), generate(19, 29));
assert_eq!(at.read("xx03"), generate(29, 39));
assert_eq!(at.read("xx04"), generate(39, 49));
assert_eq!(at.read("xx05"), generate(49, 51));
}
#[test]
fn test_skip_to_match() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%23%"])
.succeeds()
.stdout_only("84\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), generate(23, 51));
}
#[test]
fn test_skip_to_match_sequence1() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%0$%", "%^4%"])
.succeeds()
.stdout_only("33\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), generate(40, 51));
}
#[test]
fn test_skip_to_match_sequence2() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%0$%", "{1}", "%^4%"])
.succeeds()
.stdout_only("33\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), generate(40, 51));
}
#[test]
fn test_skip_to_match_sequence3() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%0$%", "{1}", "/^4/"])
.succeeds()
.stdout_only("60\n33\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(20, 40));
assert_eq!(at.read("xx01"), generate(40, 51));
}
#[test]
fn test_skip_to_match_sequence4() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%0$%", "/^4/"])
.succeeds()
.stdout_only("90\n33\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(10, 40));
assert_eq!(at.read("xx01"), generate(40, 51));
}
#[test]
fn test_skip_to_match_offset() {
for offset in ["3", "+3"] {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", &format!("%23%{offset}")])
.succeeds()
.stdout_only("75\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), generate(26, 51));
at.remove("xx00");
}
}
#[test]
fn test_skip_to_match_offset_suppress_empty() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["-z", "-", "%a%1"])
.pipe_in("a\n")
.succeeds()
.no_output();
assert!(!at.file_exists("xx00"));
}
#[test]
fn test_skip_to_match_negative_offset() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%23%-3"])
.succeeds()
.stdout_only("93\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), generate(20, 51));
}
#[test]
fn test_skip_to_match_repeat_always() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%0$%", "{*}"])
.succeeds()
.no_stdout();
let count = glob(&at.plus_as_string("xx*")).unwrap().count();
assert_eq!(count, 0);
}
#[test]
fn test_mix() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "13", "%25%", "/0$/"])
.succeeds()
.stdout_only("27\n15\n63\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 3);
assert_eq!(at.read("xx00"), generate(1, 13));
assert_eq!(at.read("xx01"), generate(25, 30));
assert_eq!(at.read("xx02"), generate(30, 51));
}
#[test]
fn test_option_keep() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["-k", "numbers50.txt", "/20/", "/nope/"])
.fails()
.stderr_is("csplit: '/nope/': match not found\n")
.stdout_is("48\n93\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 20));
assert_eq!(at.read("xx01"), generate(20, 51));
}
#[test]
fn test_option_quiet() {
for arg in ["-q", "--quiet", "-s", "--silent"] {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&[arg, "numbers50.txt", "13", "%25%", "/0$/"])
.succeeds()
.no_stdout();
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 3);
assert_eq!(at.read("xx00"), generate(1, 13));
assert_eq!(at.read("xx01"), generate(25, 30));
assert_eq!(at.read("xx02"), generate(30, 51));
at.remove("xx00");
at.remove("xx01");
at.remove("xx02");
}
}
#[test]
fn test_option_prefix() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--prefix", "dog", "numbers50.txt", "13", "%25%", "/0$/"])
.succeeds()
.stdout_only("27\n15\n63\n");
let count = glob(&at.plus_as_string("dog*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 3);
assert_eq!(at.read("dog00"), generate(1, 13));
assert_eq!(at.read("dog01"), generate(25, 30));
assert_eq!(at.read("dog02"), generate(30, 51));
}
#[test]
fn test_negative_offset_at_start() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["-", "/a/-1", "{*}"])
.pipe_in("\na\n")
.succeeds()
.stdout_only("0\n3\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), "");
assert_eq!(at.read("xx01"), "\na\n");
}
#[test]
fn test_up_to_match_option_suppress_matched() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "--suppress-matched", "/0$/", "{*}"])
.succeeds()
.stdout_only("18\n27\n27\n27\n27\n0\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 6);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(11, 20));
assert_eq!(at.read("xx02"), generate(21, 30));
assert_eq!(at.read("xx03"), generate(31, 40));
assert_eq!(at.read("xx04"), generate(41, 50));
assert_eq!(at.read("xx05"), "");
}
#[test]
fn test_up_to_match_offset_option_suppress_matched() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "--suppress-matched", "/10/+4"])
.succeeds()
.stdout_only("30\n108\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 14));
assert_eq!(at.read("xx01"), generate(15, 51));
}
#[test]
fn test_up_to_match_negative_offset_option_suppress_matched() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "--suppress-matched", "/10/-4"])
.succeeds()
.stdout_only("10\n129\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 6));
assert_eq!(at.read("xx01"), generate(7, 51));
}
#[test]
fn test_up_to_line_option_suppress_matched() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "--suppress-matched", "10"])
.succeeds()
.stdout_only("18\n120\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(11, 51));
}
#[test]
fn test_skip_to_match_option_suppress_matched() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "--suppress-matched", "%0$%"])
.succeeds()
.stdout_only("120\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), generate(11, 51));
}
#[test]
fn test_option_elide_empty_file1() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "--suppress-matched", "-z", "/0$/", "{*}"])
.succeeds()
.stdout_only("18\n27\n27\n27\n27\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 5);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(11, 20));
assert_eq!(at.read("xx02"), generate(21, 30));
assert_eq!(at.read("xx03"), generate(31, 40));
assert_eq!(at.read("xx04"), generate(41, 50));
}
#[test]
fn test_option_elide_empty_file2() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["-", "-z", "/a/-1", "{*}"])
.pipe_in("\na\n")
.succeeds()
.stdout_only("3\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), "\na\n");
}
#[test]
fn test_up_to_match_context_overflow() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/45/+10"])
.fails()
.stdout_is("141\n")
.stderr_is("csplit: '/45/+10': line number out of range\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/45/+10", "-k"])
.fails()
.stdout_is("141\n")
.stderr_is("csplit: '/45/+10': line number out of range\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), generate(1, 51));
}
#[test]
fn test_skip_to_match_context_underflow() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%5%-10"])
.fails()
.stdout_is("")
.stderr_is("csplit: '%5%-10': line number out of range\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%5%-10", "-k"])
.fails()
.stdout_is("")
.stderr_is("csplit: '%5%-10': line number out of range\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_skip_to_match_context_overflow() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%45%+10"])
.fails()
.stderr_is("csplit: '%45%+10': line number out of range\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%45%+10", "-k"])
.fails()
.stderr_only("csplit: '%45%+10': line number out of range\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_up_to_no_match1() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/4/", "/nope/"])
.fails()
.stdout_is("6\n135\n")
.stderr_is("csplit: '/nope/': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/4/", "/nope/", "-k"])
.fails()
.stdout_is("6\n135\n")
.stderr_is("csplit: '/nope/': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 4));
assert_eq!(at.read("xx01"), generate(4, 51));
}
#[test]
fn test_up_to_no_match2() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/4/", "/nope/", "{50}"])
.fails()
.stdout_is("6\n135\n")
.stderr_is("csplit: '/nope/': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/4/", "/nope/", "{50}", "-k"])
.fails()
.stdout_is("6\n135\n")
.stderr_is("csplit: '/nope/': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 4));
assert_eq!(at.read("xx01"), generate(4, 51));
}
#[test]
fn test_up_to_no_match3() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/0$/", "{50}"])
.fails()
.stdout_is("18\n30\n30\n30\n30\n3\n")
.stderr_is("csplit: '/0$/': match not found on repetition 5\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/0$/", "{50}", "-k"])
.fails()
.stdout_is("18\n30\n30\n30\n30\n3\n")
.stderr_is("csplit: '/0$/': match not found on repetition 5\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 6);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(10, 20));
assert_eq!(at.read("xx02"), generate(20, 30));
assert_eq!(at.read("xx03"), generate(30, 40));
assert_eq!(at.read("xx04"), generate(40, 50));
assert_eq!(at.read("xx05"), "50\n");
}
#[test]
fn test_up_to_no_match4() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/nope/", "/4/"])
.fails()
.stdout_is("141\n")
.stderr_is("csplit: '/nope/': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/nope/", "/4/", "-k"])
.fails()
.stdout_is("141\n")
.stderr_is("csplit: '/nope/': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), generate(1, 51));
}
#[test]
fn test_up_to_no_match5() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/nope/", "{*}"])
.succeeds()
.stdout_only("141\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), generate(1, 51));
}
#[test]
fn test_up_to_no_match6() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/nope/-5"])
.fails()
.stdout_is("141\n")
.stderr_is("csplit: '/nope/-5': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/nope/-5", "-k"])
.fails()
.stdout_is("141\n")
.stderr_is("csplit: '/nope/-5': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), generate(1, 51));
}
#[test]
fn test_up_to_no_match7() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/nope/+5"])
.fails()
.stdout_is("141\n")
.stderr_is("csplit: '/nope/+5': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/nope/+5", "-k"])
.fails()
.stdout_is("141\n")
.stderr_is("csplit: '/nope/+5': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), generate(1, 51));
}
#[test]
fn test_skip_to_no_match1() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%nope%"])
.fails()
.stderr_only("csplit: '%nope%': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_skip_to_no_match2() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%nope%", "{50}"])
.fails()
.stderr_only("csplit: '%nope%': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_skip_to_no_match3() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%0$%", "{50}"])
.fails()
.stderr_only("csplit: '%0$%': match not found on repetition 5\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_skip_to_no_match4() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%nope%", "/4/"])
.fails()
.stderr_only("csplit: '%nope%': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_skip_to_no_match5() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%nope%", "{*}"])
.succeeds()
.no_stderr()
.no_stdout();
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_skip_to_no_match6() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%nope%-5"])
.fails()
.stderr_only("csplit: '%nope%-5': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_skip_to_no_match7() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%nope%+5"])
.fails()
.stderr_only("csplit: '%nope%+5': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_no_match() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "%nope%"])
.fails()
.stderr_only("csplit: '%nope%': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/nope/"])
.fails()
.stdout_is("141\n")
.stderr_is("csplit: '/nope/': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_too_small_line_num() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/20/", "10", "/40/"])
.succeeds()
.stdout_only("48\n0\n60\n33\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 4);
assert_eq!(at.read("xx00"), generate(1, 20));
assert_eq!(at.read("xx01"), "");
assert_eq!(at.read("xx02"), generate(20, 40));
assert_eq!(at.read("xx03"), generate(40, 51));
}
#[test]
fn test_too_small_line_num_equal() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/20/", "20"])
.succeeds()
.stdout_only("48\n0\n93\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 3);
assert_eq!(at.read("xx00"), generate(1, 20));
assert_eq!(at.read("xx01"), "");
assert_eq!(at.read("xx02"), generate(20, 51));
}
#[test]
fn test_too_small_line_num_elided() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "-z", "/20/", "10", "/40/"])
.succeeds()
.stdout_only("48\n60\n33\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 3);
assert_eq!(at.read("xx00"), generate(1, 20));
assert_eq!(at.read("xx01"), generate(20, 40));
assert_eq!(at.read("xx02"), generate(40, 51));
}
#[test]
fn test_too_small_line_num_negative_offset() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/20/-5", "10", "/40/"])
.succeeds()
.stdout_only("33\n0\n75\n33\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 4);
assert_eq!(at.read("xx00"), generate(1, 15));
assert_eq!(at.read("xx01"), "");
assert_eq!(at.read("xx02"), generate(15, 40));
assert_eq!(at.read("xx03"), generate(40, 51));
}
#[test]
fn test_too_small_line_num_twice() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/20/", "10", "15", "/40/"])
.succeeds()
.stdout_only("48\n0\n0\n60\n33\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 5);
assert_eq!(at.read("xx00"), generate(1, 20));
assert_eq!(at.read("xx01"), "");
assert_eq!(at.read("xx02"), "");
assert_eq!(at.read("xx03"), generate(20, 40));
assert_eq!(at.read("xx04"), generate(40, 51));
}
#[test]
fn test_too_small_line_num_repeat() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/20/", "10", "{*}"])
.fails()
.stderr_is("csplit: '10': line number out of range on repetition 5\n")
.stdout_is("48\n0\n0\n30\n30\n30\n3\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/20/", "10", "{*}", "-k"])
.fails()
.stderr_is("csplit: '10': line number out of range on repetition 5\n")
.stdout_is("48\n0\n0\n30\n30\n30\n3\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 7);
assert_eq!(at.read("xx00"), generate(1, 20));
assert_eq!(at.read("xx01"), "");
assert_eq!(at.read("xx02"), "");
assert_eq!(at.read("xx03"), generate(20, 30));
assert_eq!(at.read("xx04"), generate(30, 40));
assert_eq!(at.read("xx05"), generate(40, 50));
assert_eq!(at.read("xx06"), "50\n");
}
#[test]
fn test_line_num_out_of_range1() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "100"])
.fails()
.stdout_is("141\n")
.stderr_is("csplit: '100': line number out of range\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "100", "-k"])
.fails()
.stdout_is("141\n")
.stderr_is("csplit: '100': line number out of range\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), generate(1, 51));
}
#[test]
fn test_line_num_out_of_range2() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "10", "100"])
.fails()
.stdout_is("18\n123\n")
.stderr_is("csplit: '100': line number out of range\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "10", "100", "-k"])
.fails()
.stdout_is("18\n123\n")
.stderr_is("csplit: '100': line number out of range\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(10, 51));
}
#[test]
fn test_line_num_out_of_range3() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "40", "{2}"])
.fails()
.stdout_is("108\n33\n")
.stderr_is("csplit: '40': line number out of range on repetition 1\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "40", "{2}", "-k"])
.fails()
.stdout_is("108\n33\n")
.stderr_is("csplit: '40': line number out of range on repetition 1\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 40));
assert_eq!(at.read("xx01"), generate(40, 51));
}
#[test]
fn test_line_num_out_of_range4() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "40", "{*}"])
.fails()
.stdout_is("108\n33\n")
.stderr_is("csplit: '40': line number out of range on repetition 1\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "40", "{*}", "-k"])
.fails()
.stdout_is("108\n33\n")
.stderr_is("csplit: '40': line number out of range on repetition 1\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 40));
assert_eq!(at.read("xx01"), generate(40, 51));
}
#[test]
fn test_skip_to_match_negative_offset_before_a_match() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/20/-10", "/15/"])
.fails()
.stdout_is("18\n123\n")
.stderr_is("csplit: '/15/': match not found\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_skip_to_match_negative_offset_before_a_line_num() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/20/-10", "15"])
.succeeds()
.stdout_only("18\n15\n108\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 3);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(10, 15));
assert_eq!(at.read("xx02"), generate(15, 51));
}
#[test]
fn test_corner_case1() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/10/", "11"])
.succeeds()
.stdout_only("18\n3\n120\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 3);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), "10\n");
assert_eq!(at.read("xx02"), generate(11, 51));
}
#[test]
fn test_corner_case2() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/10/-5", "/10/"])
.fails()
.stderr_is("csplit: '/10/': match not found\n")
.stdout_is("8\n133\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_corner_case3() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/15/-3", "14", "/15/"])
.fails()
.stderr_is("csplit: '/15/': match not found\n")
.stdout_is("24\n6\n111\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 0);
}
#[test]
fn test_corner_case4() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/20/-10", "/30/-4"])
.succeeds()
.stdout_only("18\n48\n75\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 3);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(10, 26));
assert_eq!(at.read("xx02"), generate(26, 51));
}
#[test]
fn test_up_to_match_context_underflow() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/5/-10"])
.fails()
.stdout_is("0\n")
.stderr_is("csplit: '/5/-10': line number out of range\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/5/-10", "-k"])
.fails()
.stdout_is("0\n")
.stderr_is("csplit: '/5/-10': line number out of range\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("counting splits")
.count();
assert_eq!(count, 1);
assert_eq!(at.read("xx00"), "");
}
// the offset is out of range because of the first pattern
#[test]
fn test_line_num_range_with_up_to_match1() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "10", "/12/-5"])
.fails()
.stderr_is("csplit: '/12/-5': line number out of range\n")
.stdout_is("18\n0\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "10", "/12/-5", "-k"])
.fails()
.stderr_is("csplit: '/12/-5': line number out of range\n")
.stdout_is("18\n0\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), "");
}
// the offset is out of range because more lines are needed than physically available
#[test]
fn test_line_num_range_with_up_to_match2() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "10", "/12/-15"])
.fails()
.stderr_is("csplit: '/12/-15': line number out of range\n")
.stdout_is("18\n0\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 0);
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "10", "/12/-15", "-k"])
.fails()
.stderr_is("csplit: '/12/-15': line number out of range\n")
.stdout_is("18\n0\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), "");
}
// NOTE: output different than gnu's: the pattern /10/ is matched but should not
#[test]
fn test_line_num_range_with_up_to_match3() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "10", "/10/", "-k"])
.fails()
.stderr_is("csplit: '/10/': match not found\n")
.stdout_is("18\n123\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(10, 51));
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "/10/", "10"])
.succeeds()
.stdout_only("18\n0\n123\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 3);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), "");
assert_eq!(at.read("xx02"), generate(10, 51));
}
#[test]
fn precision_format() {
for f in ["%#6.3x", "%0#6.3x"] {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["numbers50.txt", "10", "--suffix-format", f])
.succeeds()
.stdout_only("18\n123\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx 000"), generate(1, 10));
assert_eq!(at.read("xx 0x001"), generate(10, 51));
}
}
#[test]
fn zero_error() {
let (at, mut ucmd) = at_and_ucmd!();
at.touch("in");
ucmd.args(&["in", "0"])
.fails()
.stderr_contains("0: line number must be greater");
}
#[test]
fn no_such_file() {
new_ucmd!()
.args(&["in", "0"])
.fails()
.stderr_contains("cannot open 'in' for reading: No such file or directory");
}
#[test]
fn repeat_everything() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"numbers50.txt",
"--suppress-matched",
"--suppress-matched",
"-kzsn", // spell-checker:disable-line
"2",
"-szkn3", // spell-checker:disable-line
"-b",
"%03d",
"-b%03x",
"-f",
"xxy_",
"-fxxz_", // spell-checker:disable-line
"/13/",
"9",
"{5}",
])
.fails_with_code(1)
.no_stdout()
.stderr_only("csplit: '9': line number out of range on repetition 5\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be some splits created")
.count();
assert_eq!(count, 6);
assert_eq!(at.read("xxz_000"), generate(1, 12 + 1));
assert_eq!(at.read("xxz_001"), generate(14, 17 + 1)); // FIXME: GNU starts at 15
assert_eq!(at.read("xxz_002"), generate(19, 26 + 1));
assert_eq!(at.read("xxz_003"), generate(28, 35 + 1));
assert_eq!(at.read("xxz_004"), generate(37, 44 + 1));
assert_eq!(at.read("xxz_005"), generate(46, 50 + 1));
}
#[cfg(unix)]
#[test]
fn test_named_pipe_input_file() {
let (at, mut ucmd) = at_and_ucmd!();
let mut fifo_writer =
create_named_pipe_with_writer(&at.plus_as_string("fifo"), &generate(1, 51));
let result = ucmd.args(&["fifo", "10"]).succeeds();
fifo_writer.kill().unwrap();
fifo_writer.wait().unwrap();
result.stdout_only("18\n123\n");
let count = glob(&at.plus_as_string("xx*"))
.expect("there should be splits created")
.count();
assert_eq!(count, 2);
assert_eq!(at.read("xx00"), generate(1, 10));
assert_eq!(at.read("xx01"), generate(10, 51));
}
#[cfg(unix)]
fn create_named_pipe_with_writer(path: &str, data: &str) -> std::process::Child {
// cSpell:ignore IRWXU
nix::unistd::mkfifo(path, nix::sys::stat::Mode::S_IRWXU).unwrap();
std::process::Command::new("sh")
.arg("-c")
.arg(format!("printf '{data}' > {path}"))
.spawn()
.unwrap()
}
#[test]
fn test_directory_input_file() {
let (at, mut ucmd) = at_and_ucmd!();
at.mkdir("test_directory");
#[cfg(unix)]
ucmd.args(&["test_directory", "1"])
.fails_with_code(1)
.stderr_only("csplit: read error: Is a directory\n");
#[cfg(windows)]
ucmd.args(&["test_directory", "1"])
.fails_with_code(1)
.stderr_only("csplit: cannot open 'test_directory' for reading: Permission denied\n");
}
#[test]
fn test_stdin_no_trailing_newline() {
new_ucmd!()
.args(&["-", "2"])
.pipe_in("a\nb\nc\nd")
.succeeds()
.stdout_only("2\n5\n");
}
#[test]
#[cfg(target_os = "linux")]
fn test_csplit_non_utf8_paths() {
use std::os::unix::ffi::OsStringExt;
let (at, mut ucmd) = at_and_ucmd!();
let filename = std::ffi::OsString::from_vec(vec![0xFF, 0xFE]);
std::fs::write(at.plus(&filename), b"line1\nline2\nline3\nline4\nline5\n").unwrap();
ucmd.arg(&filename).arg("3").succeeds();
}
/// Test write error detection using /dev/full
#[test]
#[cfg(target_os = "linux")]
fn test_write_error_dev_full() {
let (at, mut ucmd) = at_and_ucmd!();
at.symlink_file("/dev/full", "xx01");
ucmd.args(&["-", "2"])
.pipe_in("1\n2\n")
.fails_with_code(1)
.stderr_contains("xx01: No space left on device");
// Files cleaned up by default
assert!(!at.file_exists("xx00"));
}
/// Test write error with -k keeps files
#[test]
#[cfg(target_os = "linux")]
fn test_write_error_dev_full_keep_files() {
let (at, mut ucmd) = at_and_ucmd!();
at.symlink_file("/dev/full", "xx01");
ucmd.args(&["-k", "-", "2"])
.pipe_in("1\n2\n")
.fails_with_code(1)
.stderr_contains("xx01: No space left on device");
assert!(at.file_exists("xx00"));
assert_eq!(at.read("xx00"), "1\n");
}