From dc25ede7ff0a0fd85712bcb3a1be1e4de870bb0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20M=2E=20Bezerra?= Date: Fri, 15 Sep 2023 22:42:23 -0300 Subject: [PATCH] add ui snapshot tests these tests are used to assert on Ouch's output for error reports and progress logging --- Cargo.lock | 141 ++++++++++++++++-- Cargo.toml | 1 + ...i_test_err_compress_missing_extension.snap | 14 ++ ...test_err_decompress_missing_extension.snap | 14 ++ .../ui__ui_test_err_missing_files-2.snap | 7 + .../ui__ui_test_err_missing_files-3.snap | 7 + .../ui__ui_test_err_missing_files.snap | 7 + .../snapshots/ui__ui_test_ok_compress-2.snap | 6 + tests/snapshots/ui__ui_test_ok_compress.snap | 7 + .../snapshots/ui__ui_test_ok_decompress.snap | 8 + .../ui__ui_test_usage_help_flag-2.snap | 25 ++++ .../ui__ui_test_usage_help_flag.snap | 48 ++++++ tests/ui.rs | 100 +++++++++++++ tests/utils.rs | 25 +++- 14 files changed, 394 insertions(+), 16 deletions(-) create mode 100644 tests/snapshots/ui__ui_test_err_compress_missing_extension.snap create mode 100644 tests/snapshots/ui__ui_test_err_decompress_missing_extension.snap create mode 100644 tests/snapshots/ui__ui_test_err_missing_files-2.snap create mode 100644 tests/snapshots/ui__ui_test_err_missing_files-3.snap create mode 100644 tests/snapshots/ui__ui_test_err_missing_files.snap create mode 100644 tests/snapshots/ui__ui_test_ok_compress-2.snap create mode 100644 tests/snapshots/ui__ui_test_ok_compress.snap create mode 100644 tests/snapshots/ui__ui_test_ok_decompress.snap create mode 100644 tests/snapshots/ui__ui_test_usage_help_flag-2.snap create mode 100644 tests/snapshots/ui__ui_test_usage_help_flag.snap create mode 100644 tests/ui.rs diff --git a/Cargo.lock b/Cargo.lock index e6333b8c3..f82241f1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -62,7 +62,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -266,6 +266,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "windows-sys 0.45.0", +] + [[package]] name = "core_affinity" version = "0.8.1" @@ -353,6 +365,12 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "errno" version = "0.3.2" @@ -361,7 +379,7 @@ checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -389,7 +407,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -530,6 +548,19 @@ dependencies = [ "cfb", ] +[[package]] +name = "insta" +version = "1.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0770b0a3d4c70567f0d58331f3088b0e4c4f56c9b8d764efe654b4a5d46de3a" +dependencies = [ + "console", + "lazy_static", + "linked-hash-map", + "similar", + "yaml-rust", +] + [[package]] name = "is_executable" version = "1.0.1" @@ -720,6 +751,7 @@ dependencies = [ "gzp", "ignore", "infer", + "insta", "is_executable", "libc", "linked-hash-map", @@ -991,7 +1023,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1027,6 +1059,12 @@ version = "1.0.185" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" +[[package]] +name = "similar" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" + [[package]] name = "snap" version = "1.1.0" @@ -1109,7 +1147,7 @@ dependencies = [ "fastrand", "redox_syscall", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1327,13 +1365,37 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -1342,51 +1404,93 @@ version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" 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", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.0" @@ -1411,6 +1515,15 @@ dependencies = [ "lzma-sys", ] +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "zip" version = "0.6.6" diff --git a/Cargo.toml b/Cargo.toml index 66731b4e8..3dca850b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ clap_mangen = "0.2.13" [dev-dependencies] assert_cmd = "2.0.12" infer = "0.15.0" +insta = "1.31.0" parse-display = "0.8.2" proptest = "1.2.0" rand = { version = "0.8.5", default-features = false, features = ["small_rng", "std"] } diff --git a/tests/snapshots/ui__ui_test_err_compress_missing_extension.snap b/tests/snapshots/ui__ui_test_err_compress_missing_extension.snap new file mode 100644 index 000000000..92fb838ab --- /dev/null +++ b/tests/snapshots/ui__ui_test_err_compress_missing_extension.snap @@ -0,0 +1,14 @@ +--- +source: tests/ui.rs +expression: "run_ouch(\"ouch compress input output\", dir)" +--- +[ERROR] Cannot compress to 'output'. + - You shall supply the compression format + +hint: Try adding supported extensions (see --help): +hint: ouch compress ... output.tar.gz +hint: ouch compress ... output.zip +hint: +hint: Alternatively, you can overwrite this option by using the '--format' flag: +hint: ouch compress ... output --format tar.gz + diff --git a/tests/snapshots/ui__ui_test_err_decompress_missing_extension.snap b/tests/snapshots/ui__ui_test_err_decompress_missing_extension.snap new file mode 100644 index 000000000..b5ae3307d --- /dev/null +++ b/tests/snapshots/ui__ui_test_err_decompress_missing_extension.snap @@ -0,0 +1,14 @@ +--- +source: tests/ui.rs +expression: "run_ouch(\"ouch decompress a\", dir)" +--- +[ERROR] Cannot decompress files without extensions + - Files without supported extensions: /a + - Decompression formats are detected automatically by the file extension + +hint: Provide a file with a supported extension: +hint: ouch decompress example.tar.gz +hint: +hint: Or overwrite this option with the '--format' flag: +hint: ouch decompress /a --format tar.gz + diff --git a/tests/snapshots/ui__ui_test_err_missing_files-2.snap b/tests/snapshots/ui__ui_test_err_missing_files-2.snap new file mode 100644 index 000000000..bfa881e6a --- /dev/null +++ b/tests/snapshots/ui__ui_test_err_missing_files-2.snap @@ -0,0 +1,7 @@ +--- +source: tests/ui.rs +expression: "run_ouch(\"ouch decompress a b\", dir)" +--- +[ERROR] failed to canonicalize path `a` + - File not found + diff --git a/tests/snapshots/ui__ui_test_err_missing_files-3.snap b/tests/snapshots/ui__ui_test_err_missing_files-3.snap new file mode 100644 index 000000000..e88f1c3f6 --- /dev/null +++ b/tests/snapshots/ui__ui_test_err_missing_files-3.snap @@ -0,0 +1,7 @@ +--- +source: tests/ui.rs +expression: "run_ouch(\"ouch list a b\", dir)" +--- +[ERROR] failed to canonicalize path `a` + - File not found + diff --git a/tests/snapshots/ui__ui_test_err_missing_files.snap b/tests/snapshots/ui__ui_test_err_missing_files.snap new file mode 100644 index 000000000..549278e00 --- /dev/null +++ b/tests/snapshots/ui__ui_test_err_missing_files.snap @@ -0,0 +1,7 @@ +--- +source: tests/ui.rs +expression: "run_ouch(\"ouch compress a b\", dir)" +--- +[ERROR] failed to canonicalize path `a` + - File not found + diff --git a/tests/snapshots/ui__ui_test_ok_compress-2.snap b/tests/snapshots/ui__ui_test_ok_compress-2.snap new file mode 100644 index 000000000..f6ff7c7de --- /dev/null +++ b/tests/snapshots/ui__ui_test_ok_compress-2.snap @@ -0,0 +1,6 @@ +--- +source: tests/ui.rs +expression: "run_ouch(\"ouch compress input output.gz\", dir)" +--- +[INFO] Successfully compressed 'output.gz'. + diff --git a/tests/snapshots/ui__ui_test_ok_compress.snap b/tests/snapshots/ui__ui_test_ok_compress.snap new file mode 100644 index 000000000..a3cf31fc0 --- /dev/null +++ b/tests/snapshots/ui__ui_test_ok_compress.snap @@ -0,0 +1,7 @@ +--- +source: tests/ui.rs +expression: "run_ouch(\"ouch compress input output.zip\", dir)" +--- +[INFO] Compressing 'input'. +[INFO] Successfully compressed 'output.zip'. + diff --git a/tests/snapshots/ui__ui_test_ok_decompress.snap b/tests/snapshots/ui__ui_test_ok_decompress.snap new file mode 100644 index 000000000..a39f3446b --- /dev/null +++ b/tests/snapshots/ui__ui_test_ok_decompress.snap @@ -0,0 +1,8 @@ +--- +source: tests/ui.rs +expression: "run_ouch(\"ouch decompress output.zst\", dir)" +--- +[INFO] Failed to confirm the format of `output` by sniffing the contents, file might be misnamed +[INFO] Successfully decompressed archive in current directory. +[INFO] Files unpacked: 1 + diff --git a/tests/snapshots/ui__ui_test_usage_help_flag-2.snap b/tests/snapshots/ui__ui_test_usage_help_flag-2.snap new file mode 100644 index 000000000..b0b60d507 --- /dev/null +++ b/tests/snapshots/ui__ui_test_usage_help_flag-2.snap @@ -0,0 +1,25 @@ +--- +source: tests/ui.rs +expression: "output_to_string(ouch!(\"-h\"))" +--- +A command-line utility for easily compressing and decompressing files and directories. + +Usage: ouch [OPTIONS] + +Commands: + compress Compress one or more files into one output file [aliases: c] + decompress Decompresses one or more files, optionally into another folder [aliases: d] + list List contents of an archive [aliases: l, ls] + help Print this message or the help of the given subcommand(s) + +Options: + -y, --yes Skip [Y/n] questions positively + -n, --no Skip [Y/n] questions negatively + -A, --accessible Activate accessibility mode, reducing visual noise [env: ACCESSIBLE=] + -H, --hidden Ignores hidden files + -q, --quiet Silences output + -g, --gitignore Ignores files matched by git's ignore files + -f, --format Specify the format of the archive + -h, --help Print help (see more with '--help') + -V, --version Print version + diff --git a/tests/snapshots/ui__ui_test_usage_help_flag.snap b/tests/snapshots/ui__ui_test_usage_help_flag.snap new file mode 100644 index 000000000..71d60084b --- /dev/null +++ b/tests/snapshots/ui__ui_test_usage_help_flag.snap @@ -0,0 +1,48 @@ +--- +source: tests/ui.rs +expression: "output_to_string(ouch!(\"--help\"))" +--- +A command-line utility for easily compressing and decompressing files and directories. + +Supported formats: tar, zip, gz, xz/lzma, bz/bz2, lz4, sz, zst. + +Repository: https://github.com/ouch-org/ouch + +Usage: ouch [OPTIONS] + +Commands: + compress Compress one or more files into one output file [aliases: c] + decompress Decompresses one or more files, optionally into another folder [aliases: d] + list List contents of an archive [aliases: l, ls] + help Print this message or the help of the given subcommand(s) + +Options: + -y, --yes + Skip [Y/n] questions positively + + -n, --no + Skip [Y/n] questions negatively + + -A, --accessible + Activate accessibility mode, reducing visual noise + + [env: ACCESSIBLE=] + + -H, --hidden + Ignores hidden files + + -q, --quiet + Silences output + + -g, --gitignore + Ignores files matched by git's ignore files + + -f, --format + Specify the format of the archive + + -h, --help + Print help (see a summary with '-h') + + -V, --version + Print version + diff --git a/tests/ui.rs b/tests/ui.rs new file mode 100644 index 000000000..120808ae9 --- /dev/null +++ b/tests/ui.rs @@ -0,0 +1,100 @@ +// Snapshot tests for Ouch's output. + +#[macro_use] +mod utils; + +use std::{io, path::Path, process::Output}; + +use insta::assert_display_snapshot as ui; + +use crate::utils::run_in; + +fn testdir() -> io::Result<(tempfile::TempDir, &'static Path)> { + let dir = tempfile::tempdir()?; + let path = dir.path().to_path_buf().into_boxed_path(); + Ok((dir, Box::leak(path))) +} + +fn run_ouch(argv: &str, dir: &Path) -> String { + let output = utils::cargo_bin() + .args(argv.split_whitespace().skip(1)) + .current_dir(dir) + .output() + .unwrap_or_else(|err| { + panic!( + "Failed to run command\n\ + argv: {argv}\n\ + path: {dir:?}\n\ + err: {err}" + ) + }); + + redact_paths(&output_to_string(output), dir) +} + +// remove random tempdir paths from snapshots to make them deterministic +fn redact_paths(text: &str, path: &Path) -> String { + let path = format!("{}/", path.display()); + + text.replace(&path, "/") +} + +fn output_to_string(output: Output) -> String { + String::from_utf8(output.stdout).unwrap() + std::str::from_utf8(&output.stderr).unwrap() +} + +#[test] +fn ui_test_err_compress_missing_extension() { + let (_dropper, dir) = testdir().unwrap(); + + // prepare + run_in(dir, "touch", "input").unwrap(); + + ui!(run_ouch("ouch compress input output", dir)); +} + +#[test] +fn ui_test_err_decompress_missing_extension() { + let (_dropper, dir) = testdir().unwrap(); + + run_in(dir, "touch", "a").unwrap(); + + ui!(run_ouch("ouch decompress a", dir)); +} + +#[test] +fn ui_test_err_missing_files() { + let (_dropper, dir) = testdir().unwrap(); + + ui!(run_ouch("ouch compress a b", dir)); + ui!(run_ouch("ouch decompress a b", dir)); + ui!(run_ouch("ouch list a b", dir)); +} + +#[test] +fn ui_test_ok_compress() { + let (_dropper, dir) = testdir().unwrap(); + + // prepare + run_in(dir, "touch", "input").unwrap(); + + ui!(run_ouch("ouch compress input output.zip", dir)); + ui!(run_ouch("ouch compress input output.gz", dir)); +} + +#[test] +fn ui_test_ok_decompress() { + let (_dropper, dir) = testdir().unwrap(); + + // prepare + run_in(dir, "touch", "input").unwrap(); + run_ouch("ouch compress input output.zst", dir); + + ui!(run_ouch("ouch decompress output.zst", dir)); +} + +#[test] +fn ui_test_usage_help_flag() { + ui!(output_to_string(ouch!("--help"))); + ui!(output_to_string(ouch!("-h"))); +} diff --git a/tests/utils.rs b/tests/utils.rs index d1af39a65..bd8a66f78 100644 --- a/tests/utils.rs +++ b/tests/utils.rs @@ -1,16 +1,27 @@ -use std::{env, io::Write, path::PathBuf}; +// This warning is unavoidable when reusing testing utils. +#![allow(dead_code)] + +use std::{ + env, + ffi::OsStr, + io, + io::Write, + path::{Path, PathBuf}, + process::Output, +}; use assert_cmd::Command; use fs_err as fs; use rand::{Rng, RngCore}; +// Run ouch with the provided arguments, returns `assert_cmd::Output` #[macro_export] macro_rules! ouch { ($($e:expr),*) => { $crate::utils::cargo_bin() $(.arg($e))* .arg("--yes") - .unwrap(); + .unwrap() } } @@ -27,6 +38,16 @@ pub fn cargo_bin() -> Command { .unwrap_or_else(|| Command::cargo_bin("ouch").expect("Failed to find ouch executable")) } +/// Run a command inside of another folder. +/// +/// example: `run_in("/tmp", "touch", "a b c")` +pub fn run_in(folder: impl AsRef, bin: impl AsRef, args: &str) -> io::Result { + Command::new(bin) + .args(args.split_whitespace()) + .current_dir(folder) + .output() +} + // write random content to a file pub fn write_random_content(file: &mut impl Write, rng: &mut impl RngCore) { let mut data = Vec::new();