Skip to main content

Merge pull request #2 from alexwlchan/add-cli-tests

ID
2ac2639
date
2025-01-11 11:54:47+00:00
author
Alex Chan <alex@alexwlchan.net>
parents
d3b9dfb, ac70385
message
Merge pull request #2 from alexwlchan/add-cli-tests

Add some CLI tests
changed files
3 files, 240 additions, 3 deletions

Changed files

Cargo.lock (3555) → Cargo.lock (6718)

diff --git a/Cargo.lock b/Cargo.lock
index 51a772e..a9506ca 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,6 +3,39 @@
 version = 3
 
 [[package]]
+name = "anstyle"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+
+[[package]]
+name = "assert_cmd"
+version = "2.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d"
+dependencies = [
+ "anstyle",
+ "bstr",
+ "doc-comment",
+ "libc",
+ "predicates",
+ "predicates-core",
+ "predicates-tree",
+ "wait-timeout",
+]
+
+[[package]]
+name = "bstr"
+version = "1.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0"
+dependencies = [
+ "memchr",
+ "regex-automata",
+ "serde",
+]
+
+[[package]]
 name = "byteorder"
 version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -15,6 +48,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[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 = "getrandom"
 version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -32,6 +77,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
 
 [[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
 name = "ppv-lite86"
 version = "0.2.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -41,6 +92,33 @@ dependencies = [
 ]
 
 [[package]]
+name = "predicates"
+version = "3.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573"
+dependencies = [
+ "anstyle",
+ "difflib",
+ "predicates-core",
+]
+
+[[package]]
+name = "predicates-core"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa"
+
+[[package]]
+name = "predicates-tree"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c"
+dependencies = [
+ "predicates-core",
+ "termtree",
+]
+
+[[package]]
 name = "proc-macro2"
 version = "1.0.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -92,10 +170,37 @@ dependencies = [
 name = "randline"
 version = "0.1.0"
 dependencies = [
+ "assert_cmd",
  "rand",
 ]
 
 [[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+
+[[package]]
+name = "serde"
+version = "1.0.217"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.217"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "syn"
 version = "2.0.95"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -107,12 +212,27 @@ dependencies = [
 ]
 
 [[package]]
+name = "termtree"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
+
+[[package]]
 name = "unicode-ident"
 version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
 
 [[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"

Cargo.toml (92) → Cargo.toml (109)

diff --git a/Cargo.toml b/Cargo.toml
index 4d61b21..da61cbd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,4 +4,5 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
+assert_cmd = "2"
 rand = "0.8"

src/main.rs (1075) → src/main.rs (4232)

diff --git a/src/main.rs b/src/main.rs
index 5389f36..8d881e6 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,4 @@
-// #![deny(warnings)]
+#![deny(warnings)]
 
 use std::io::BufRead;
 use std::iter::Iterator;
@@ -17,8 +17,8 @@ fn main() {
     let k = match args.len() {
         1 => 1,
         2 => match args[1].parse::<usize>() {
-            Ok(parsed_k) => parsed_k,
-            Err(_) => {
+            Ok(parsed_k) if parsed_k > 0 => parsed_k,
+            _ => {
                 eprintln!("Usage: randline [k]");
                 std::process::exit(1)
             }
@@ -43,3 +43,119 @@ fn main() {
         println!("{}", line);
     }
 }
+
+#[cfg(test)]
+mod cli_tests {
+    use assert_cmd::Command;
+
+    // Note: for the purposes of the CLI tests, I trust that the reservoir
+    // sampling code works correctly -- that's tested separately.  I'm just
+    // checking the CLI parses the options correctly, so all the input lines
+    // are the same for easy assertions.
+
+    // If you call `randline` without any arguments, it picks a single line.
+    #[test]
+    fn it_selects_a_single_line_if_no_arg() {
+        Command::cargo_bin("randline")
+            .unwrap()
+            .write_stdin("a\na\na\na\na\na\n")
+            .assert()
+            .success()
+            .stdout("a\n")
+            .stderr("");
+    }
+
+    // If you pass an argument `k` and there are more lines than `k`,
+    // it selects a subset of them.
+    #[test]
+    fn it_selects_k_lines_if_more_lines_than_k() {
+        Command::cargo_bin("randline")
+            .unwrap()
+            .arg("2")
+            .write_stdin("a\na\na\na\na\na\n")
+            .assert()
+            .success()
+            .stdout("a\na\n")
+            .stderr("");
+    }
+
+    // If you pass an argument `k` and there are that number of lines,
+    // it selects all of them.
+    #[test]
+    fn it_selects_k_lines_if_equal_lines_to_k() {
+        Command::cargo_bin("randline")
+            .unwrap()
+            .arg("2")
+            .write_stdin("a\na\n")
+            .assert()
+            .success()
+            .stdout("a\na\n")
+            .stderr("");
+    }
+
+    // If you pass an argument `k` and there are less lines than `k`,
+    // it selects all of them.
+    #[test]
+    fn it_selects_k_lines_if_less_lines_than_k() {
+        Command::cargo_bin("randline")
+            .unwrap()
+            .arg("5")
+            .write_stdin("a\na\n")
+            .assert()
+            .success()
+            .stdout("a\na\n")
+            .stderr("");
+    }
+
+    // Passing a non-integer argument is an error.
+    #[test]
+    fn it_fails_if_non_integer_argument() {
+        Command::cargo_bin("randline")
+            .unwrap()
+            .arg("XXX")
+            .assert()
+            .failure()
+            .code(1)
+            .stdout("")
+            .stderr("Usage: randline [k]\n");
+    }
+
+    // Passing k=0 is an error.
+    #[test]
+    fn it_fails_if_k_equals_zero() {
+        Command::cargo_bin("randline")
+            .unwrap()
+            .arg("0")
+            .assert()
+            .failure()
+            .code(1)
+            .stdout("")
+            .stderr("Usage: randline [k]\n");
+    }
+
+    // Passing k<0 is an error.
+    #[test]
+    fn it_fails_if_k_negative() {
+        Command::cargo_bin("randline")
+            .unwrap()
+            .arg("-1")
+            .assert()
+            .failure()
+            .code(1)
+            .stdout("")
+            .stderr("Usage: randline [k]\n");
+    }
+
+    // Passing more than one argument is an error.
+    #[test]
+    fn it_fails_if_too_many_args() {
+        Command::cargo_bin("randline")
+            .unwrap()
+            .args(&["1", "2", "3"])
+            .assert()
+            .failure()
+            .code(1)
+            .stdout("")
+            .stderr("Usage: randline [k]\n");
+    }
+}