initial commit
This commit is contained in:
421
tests/cli.rs
Normal file
421
tests/cli.rs
Normal file
@@ -0,0 +1,421 @@
|
||||
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",
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user