commit 2b1a912efed7172b751cf93f6bb8b9a19fbad09d Author: minhtrannhat Date: Wed Sep 20 01:55:43 2023 -0400 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..343d220 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +tests/expected/ +tests/inputs/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0ae5cbb --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,465 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "assert_cmd" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bstr" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_lex" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "headr" +version = "0.1.0" +dependencies = [ + "assert_cmd", + "clap", + "predicates", + "rand", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "memchr" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "predicates" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" +dependencies = [ + "anstyle", + "difflib", + "float-cmp", + "itertools", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" + +[[package]] +name = "predicates-tree" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "regex" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "serde" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.188" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d46314f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "headr" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = { version = "4.4.2", features = ["cargo", "help"] } + +[dev-dependencies] +assert_cmd = "2.0.12" +predicates = "3.0.3" +rand = "0.8.5" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..4e93bcd --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,69 @@ +use clap::builder::{Arg, Command}; +use clap::{ + crate_authors, crate_description, crate_name, crate_version, value_parser, ArgAction, + ArgMatches, +}; +use std::error::Error; + +type HeadrResult = Result>; + +#[derive(Debug)] +pub struct Config { + files: Vec, + lines: usize, + bytes: Option, +} + +pub fn get_args() -> HeadrResult { + let matches: ArgMatches = Command::new(crate_name!()) + .version(crate_version!()) + .author(crate_authors!("\n")) + .about(crate_description!()) + .help_template( + "\ +{before-help}{name} {version} + {author-with-newline}{about-with-newline} +{usage-heading} {usage} +{all-args} {after-help} +", + ) + .arg( + Arg::new("file") + .value_name("FILE") + .help("Input file(s)") + .num_args(1..) + .default_values(["-"]), + ) + .arg( + Arg::new("number") + .short('n') + .long("lines") + .help( + "Print the first K lines instead of the first 10 with the leading '-', print all but the last K lines of each file") + .num_args(1) + .default_value("10") + .value_parser(value_parser!(u16).range(0..)) + .action(ArgAction::Set) + ) + .arg( + Arg::new("bytes") + .short('c') + .long("bytes") + .help( + "print the first K bytes of each file; with the leading '-', print all but the last K lines of each file") + .num_args(1) + .value_parser(value_parser!(u16).range(0..)) + .action(ArgAction::Set) + ) + .get_matches(); + + Ok(Config { + files: matches + .get_many::("file") + .expect("Must contains valid filepaths") + .cloned() + .collect(), + lines: *matches.get_one("number").expect(""), + bytes: *matches.get_one("bytes").expect(""), + }) +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..09a4800 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,6 @@ +fn main() { + if let Err(e) = headr::get_args().and_then(headr::run) { + eprintln!("{}", e); + std::process::exit(1); + } +} diff --git a/tests/cli.rs b/tests/cli.rs new file mode 100644 index 0000000..2bdb022 --- /dev/null +++ b/tests/cli.rs @@ -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>; + +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 ' cannot be \ + used with '--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", + ) +}