422 lines
9.5 KiB
Rust
422 lines
9.5 KiB
Rust
use assert_cmd::Command;
|
|
use predicates::prelude::*;
|
|
use rand::{distributions::Alphanumeric, Rng};
|
|
use std::io::prelude::*;
|
|
use std::{
|
|
error::Error,
|
|
fs::{self, File},
|
|
};
|
|
|
|
type TestResult = Result<(), Box<dyn Error>>;
|
|
|
|
const PRG: &str = "headr";
|
|
const EMPTY: &str = "./tests/inputs/empty.txt";
|
|
const ONE: &str = "./tests/inputs/one.txt";
|
|
const TWO: &str = "./tests/inputs/two.txt";
|
|
const THREE: &str = "./tests/inputs/three.txt";
|
|
const TEN: &str = "./tests/inputs/ten.txt";
|
|
|
|
// --------------------------------------------------
|
|
fn random_string() -> String {
|
|
rand::thread_rng()
|
|
.sample_iter(&Alphanumeric)
|
|
.take(7)
|
|
.map(char::from)
|
|
.collect()
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
fn gen_bad_file() -> String {
|
|
loop {
|
|
let filename = random_string();
|
|
if fs::metadata(&filename).is_err() {
|
|
return filename;
|
|
}
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn dies_bad_bytes() -> TestResult {
|
|
let bad = random_string();
|
|
let expected = format!("illegal byte count -- {}", &bad);
|
|
Command::cargo_bin(PRG)?
|
|
.args(&["-c", &bad, EMPTY])
|
|
.assert()
|
|
.failure()
|
|
.stderr(predicate::str::contains(expected));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn dies_bad_lines() -> TestResult {
|
|
let bad = random_string();
|
|
let expected = format!("illegal line count -- {}", &bad);
|
|
Command::cargo_bin(PRG)?
|
|
.args(&["-n", &bad, EMPTY])
|
|
.assert()
|
|
.failure()
|
|
.stderr(predicate::str::contains(expected));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn dies_bytes_and_lines() -> TestResult {
|
|
let msg = "The argument '--lines <LINES>' cannot be \
|
|
used with '--bytes <BYTES>'";
|
|
|
|
Command::cargo_bin(PRG)?
|
|
.args(&["-n", "1", "-c", "2"])
|
|
.assert()
|
|
.failure()
|
|
.stderr(predicate::str::contains(msg));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn skips_bad_file() -> TestResult {
|
|
let bad = gen_bad_file();
|
|
let expected = format!("{}: .* [(]os error 2[)]", bad);
|
|
Command::cargo_bin(PRG)?
|
|
.args([EMPTY, &bad, ONE])
|
|
.assert()
|
|
.stderr(predicate::str::is_match(expected)?);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
fn run(args: &[&str], expected_file: &str) -> TestResult {
|
|
// Extra work here due to lossy UTF
|
|
let mut file = File::open(expected_file)?;
|
|
let mut buffer = Vec::new();
|
|
file.read_to_end(&mut buffer)?;
|
|
let expected = String::from_utf8_lossy(&buffer);
|
|
|
|
Command::cargo_bin(PRG)?
|
|
.args(args)
|
|
.assert()
|
|
.success()
|
|
.stdout(predicate::eq(&expected.as_bytes() as &[u8]));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
fn run_stdin(
|
|
args: &[&str],
|
|
input_file: &str,
|
|
expected_file: &str,
|
|
) -> TestResult {
|
|
// Extra work here due to lossy UTF
|
|
let mut file = File::open(expected_file)?;
|
|
let mut buffer = Vec::new();
|
|
file.read_to_end(&mut buffer)?;
|
|
let expected = String::from_utf8_lossy(&buffer);
|
|
let input = fs::read_to_string(input_file)?;
|
|
|
|
Command::cargo_bin(PRG)?
|
|
.write_stdin(input)
|
|
.args(args)
|
|
.assert()
|
|
.stdout(predicate::eq(&expected.as_bytes() as &[u8]));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn empty() -> TestResult {
|
|
run(&[EMPTY], "tests/expected/empty.txt.out")
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn empty_n2() -> TestResult {
|
|
run(&[EMPTY, "-n", "2"], "tests/expected/empty.txt.n2.out")
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn empty_n4() -> TestResult {
|
|
run(&[EMPTY, "-n", "4"], "tests/expected/empty.txt.n4.out")
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn empty_c2() -> TestResult {
|
|
run(&[EMPTY, "-c", "2"], "tests/expected/empty.txt.c2.out")
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn empty_c4() -> TestResult {
|
|
run(&[EMPTY, "-c", "4"], "tests/expected/empty.txt.c4.out")
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn one() -> TestResult {
|
|
run(&[ONE], "tests/expected/one.txt.out")
|
|
}
|
|
|
|
#[test]
|
|
fn one_n2() -> TestResult {
|
|
run(&[ONE, "-n", "2"], "tests/expected/one.txt.n2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn one_n4() -> TestResult {
|
|
run(&[ONE, "-n", "4"], "tests/expected/one.txt.n4.out")
|
|
}
|
|
|
|
#[test]
|
|
fn one_c1() -> TestResult {
|
|
run(&[ONE, "-c", "1"], "tests/expected/one.txt.c1.out")
|
|
}
|
|
|
|
#[test]
|
|
fn one_c2() -> TestResult {
|
|
run(&[ONE, "-c", "2"], "tests/expected/one.txt.c2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn one_c4() -> TestResult {
|
|
run(&[ONE, "-c", "4"], "tests/expected/one.txt.c4.out")
|
|
}
|
|
|
|
#[test]
|
|
fn one_stdin() -> TestResult {
|
|
run_stdin(&[], ONE, "tests/expected/one.txt.out")
|
|
}
|
|
|
|
#[test]
|
|
fn one_n2_stdin() -> TestResult {
|
|
run_stdin(&["-n", "2"], ONE, "tests/expected/one.txt.n2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn one_n4_stdin() -> TestResult {
|
|
run_stdin(&["-n", "4"], ONE, "tests/expected/one.txt.n4.out")
|
|
}
|
|
|
|
#[test]
|
|
fn one_c1_stdin() -> TestResult {
|
|
run_stdin(&["-c", "1"], ONE, "tests/expected/one.txt.c1.out")
|
|
}
|
|
|
|
#[test]
|
|
fn one_c2_stdin() -> TestResult {
|
|
run_stdin(&["-c", "2"], ONE, "tests/expected/one.txt.c2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn one_c4_stdin() -> TestResult {
|
|
run_stdin(&["-c", "4"], ONE, "tests/expected/one.txt.c4.out")
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn two() -> TestResult {
|
|
run(&[TWO], "tests/expected/two.txt.out")
|
|
}
|
|
|
|
#[test]
|
|
fn two_n2() -> TestResult {
|
|
run(&[TWO, "-n", "2"], "tests/expected/two.txt.n2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn two_n4() -> TestResult {
|
|
run(&[TWO, "-n", "4"], "tests/expected/two.txt.n4.out")
|
|
}
|
|
|
|
#[test]
|
|
fn two_c2() -> TestResult {
|
|
run(&[TWO, "-c", "2"], "tests/expected/two.txt.c2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn two_c4() -> TestResult {
|
|
run(&[TWO, "-c", "4"], "tests/expected/two.txt.c4.out")
|
|
}
|
|
|
|
#[test]
|
|
fn two_stdin() -> TestResult {
|
|
run_stdin(&[], TWO, "tests/expected/two.txt.out")
|
|
}
|
|
|
|
#[test]
|
|
fn two_n2_stdin() -> TestResult {
|
|
run_stdin(&["-n", "2"], TWO, "tests/expected/two.txt.n2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn two_n4_stdin() -> TestResult {
|
|
run_stdin(&["-n", "4"], TWO, "tests/expected/two.txt.n4.out")
|
|
}
|
|
|
|
#[test]
|
|
fn two_c2_stdin() -> TestResult {
|
|
run_stdin(&["-c", "2"], TWO, "tests/expected/two.txt.c2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn two_c4_stdin() -> TestResult {
|
|
run_stdin(&["-c", "4"], TWO, "tests/expected/two.txt.c4.out")
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn three() -> TestResult {
|
|
run(&[THREE], "tests/expected/three.txt.out")
|
|
}
|
|
|
|
#[test]
|
|
fn three_n2() -> TestResult {
|
|
run(&[THREE, "-n", "2"], "tests/expected/three.txt.n2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn three_n4() -> TestResult {
|
|
run(&[THREE, "-n", "4"], "tests/expected/three.txt.n4.out")
|
|
}
|
|
|
|
#[test]
|
|
fn three_c2() -> TestResult {
|
|
run(&[THREE, "-c", "2"], "tests/expected/three.txt.c2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn three_c4() -> TestResult {
|
|
run(&[THREE, "-c", "4"], "tests/expected/three.txt.c4.out")
|
|
}
|
|
|
|
#[test]
|
|
fn three_stdin() -> TestResult {
|
|
run_stdin(&[], THREE, "tests/expected/three.txt.out")
|
|
}
|
|
|
|
#[test]
|
|
fn three_n2_stdin() -> TestResult {
|
|
run_stdin(&["-n", "2"], THREE, "tests/expected/three.txt.n2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn three_n4_stdin() -> TestResult {
|
|
run_stdin(&["-n", "4"], THREE, "tests/expected/three.txt.n4.out")
|
|
}
|
|
|
|
#[test]
|
|
fn three_c2_stdin() -> TestResult {
|
|
run_stdin(&["-c", "2"], THREE, "tests/expected/three.txt.c2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn three_c4_stdin() -> TestResult {
|
|
run_stdin(&["-c", "4"], THREE, "tests/expected/three.txt.c4.out")
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn ten() -> TestResult {
|
|
run(&[TEN], "tests/expected/ten.txt.out")
|
|
}
|
|
|
|
#[test]
|
|
fn ten_n2() -> TestResult {
|
|
run(&[TEN, "-n", "2"], "tests/expected/ten.txt.n2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn ten_n4() -> TestResult {
|
|
run(&[TEN, "-n", "4"], "tests/expected/ten.txt.n4.out")
|
|
}
|
|
|
|
#[test]
|
|
fn ten_c2() -> TestResult {
|
|
run(&[TEN, "-c", "2"], "tests/expected/ten.txt.c2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn ten_c4() -> TestResult {
|
|
run(&[TEN, "-c", "4"], "tests/expected/ten.txt.c4.out")
|
|
}
|
|
|
|
#[test]
|
|
fn ten_stdin() -> TestResult {
|
|
run_stdin(&[], TEN, "tests/expected/ten.txt.out")
|
|
}
|
|
|
|
#[test]
|
|
fn ten_n2_stdin() -> TestResult {
|
|
run_stdin(&["-n", "2"], TEN, "tests/expected/ten.txt.n2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn ten_n4_stdin() -> TestResult {
|
|
run_stdin(&["-n", "4"], TEN, "tests/expected/ten.txt.n4.out")
|
|
}
|
|
|
|
#[test]
|
|
fn ten_c2_stdin() -> TestResult {
|
|
run_stdin(&["-c", "2"], TEN, "tests/expected/ten.txt.c2.out")
|
|
}
|
|
|
|
#[test]
|
|
fn ten_c4_stdin() -> TestResult {
|
|
run_stdin(&["-c", "4"], TEN, "tests/expected/ten.txt.c4.out")
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
#[test]
|
|
fn multiple_files() -> TestResult {
|
|
run(&[EMPTY, ONE, TWO, THREE, TEN], "tests/expected/all.out")
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_files_n2() -> TestResult {
|
|
run(
|
|
&[EMPTY, ONE, TWO, THREE, TEN, "-n", "2"],
|
|
"tests/expected/all.n2.out",
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_files_n4() -> TestResult {
|
|
run(
|
|
&["-n", "4", EMPTY, ONE, TWO, THREE, TEN],
|
|
"tests/expected/all.n4.out",
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_files_c1() -> TestResult {
|
|
run(
|
|
&[EMPTY, ONE, TWO, THREE, TEN, "-c", "1"],
|
|
"tests/expected/all.c1.out",
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_files_c2() -> TestResult {
|
|
run(
|
|
&[EMPTY, ONE, TWO, THREE, TEN, "-c", "2"],
|
|
"tests/expected/all.c2.out",
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_files_c4() -> TestResult {
|
|
run(
|
|
&["-c", "4", EMPTY, ONE, TWO, THREE, TEN],
|
|
"tests/expected/all.c4.out",
|
|
)
|
|
}
|