From 1d0fa2c6ce7a088c353c08e20f9f3c30fe82e1cf Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 20 Jul 2023 14:42:58 -0500 Subject: [PATCH] refactor(complete): Make test code reusable --- Cargo.lock | 4 +- clap_complete/Cargo.toml | 2 +- clap_complete/tests/testsuite/bash.rs | 81 ++--------------------- clap_complete/tests/testsuite/common.rs | 87 +++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 79c2f6ad..40a9e126 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -646,9 +646,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "completest" -version = "0.0.3" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6feacc4465b103a9c3ee1ca2de3fc8336822145bed52ede7cd80f9b32a1ab329" +checksum = "e6b57d79ef15ead5db9b7168af5a3008a4499d8048005ea3b3868748f12b27ad" dependencies = [ "ptyprocess", "vt100", diff --git a/clap_complete/Cargo.toml b/clap_complete/Cargo.toml index e4d14224..111bd1db 100644 --- a/clap_complete/Cargo.toml +++ b/clap_complete/Cargo.toml @@ -43,7 +43,7 @@ unicode-xid = { version = "0.2.2", optional = true } snapbox = { version = "0.4.11", features = ["diff", "examples"] } # Cutting out `filesystem` feature trycmd = { version = "0.14.16", default-features = false, features = ["color-auto", "diff", "examples"] } -completest = "0.0.3" +completest = "0.0.4" clap = { path = "../", version = "4.0.0", default-features = false, features = ["std", "derive", "help"] } [[example]] diff --git a/clap_complete/tests/testsuite/bash.rs b/clap_complete/tests/testsuite/bash.rs index 806ba0d3..8f6a2daa 100644 --- a/clap_complete/tests/testsuite/bash.rs +++ b/clap_complete/tests/testsuite/bash.rs @@ -139,46 +139,22 @@ fn subcommand_last() { #[test] #[cfg(unix)] fn register_completion() { - if !has_command("bash") { + if !common::has_command("bash") { return; } - let shell = "bash"; - let home = std::path::Path::new("tests/snapshots/home/test/bash").to_owned(); - let bin_path = snapbox::cmd::compile_example("test", []).unwrap(); - let bin_root = bin_path.parent().unwrap().to_owned(); - - let registration = std::process::Command::new(&bin_path) - .arg(format!("--generate={shell}")) - .output() - .unwrap(); - assert!( - registration.status.success(), - "{}", - String::from_utf8_lossy(®istration.stderr) - ); - let registration = std::str::from_utf8(®istration.stdout).unwrap(); - assert!(!registration.is_empty()); - - let runtime = completest::BashRuntime::new(bin_root, home).unwrap(); - - runtime.register("test", registration).unwrap(); + common::register_example("test", completest::Shell::Bash); } #[test] #[cfg(unix)] fn complete() { - if !has_command("bash") { + if !common::has_command("bash") { return; } - let shell = "bash"; - let home = std::path::PathBuf::from(format!("tests/snapshots/home/test/{shell}")); - let bin_path = snapbox::cmd::compile_example("test", []).unwrap(); - let bin_root = bin_path.parent().unwrap().to_owned(); - let term = completest::Term::new(); - let runtime = completest::BashRuntime::with_home(bin_root, home); + let runtime = common::load_runtime("test", completest::Shell::Bash); let input = "test \t\t"; let expected = r#"% @@ -187,52 +163,3 @@ fn complete() { let actual = runtime.complete(input, &term).unwrap(); snapbox::assert_eq(expected, actual); } - -fn has_command(command: &str) -> bool { - let output = match std::process::Command::new(command) - .arg("--version") - .output() - { - Ok(output) => output, - Err(e) => { - // CI is expected to support all of the commands - if is_ci() && cfg!(linux) { - panic!( - "expected command `{}` to be somewhere in PATH: {}", - command, e - ); - } - return false; - } - }; - if !output.status.success() { - panic!( - "expected command `{}` to be runnable, got error {}:\n\ - stderr:{}\n\ - stdout:{}\n", - command, - output.status, - String::from_utf8_lossy(&output.stderr), - String::from_utf8_lossy(&output.stdout) - ); - } - let stdout = String::from_utf8_lossy(&output.stdout); - println!( - "$ bash --version -{}", - stdout - ); - if cfg!(target_os = "macos") && stdout.starts_with("GNU bash, version 3") { - return false; - } - - true -} - -/// Whether or not this running in a Continuous Integration environment. -fn is_ci() -> bool { - // Consider using `tracked_env` instead of option_env! when it is stabilized. - // `tracked_env` will handle changes, but not require rebuilding the macro - // itself like option_env does. - option_env!("CI").is_some() || option_env!("TF_BUILD").is_some() -} diff --git a/clap_complete/tests/testsuite/common.rs b/clap_complete/tests/testsuite/common.rs index 1eb530f1..15b1caf7 100644 --- a/clap_complete/tests/testsuite/common.rs +++ b/clap_complete/tests/testsuite/common.rs @@ -295,3 +295,90 @@ pub fn assert_matches_path( .normalize_paths(false) .matches_path(expected_path, buf); } + +pub fn has_command(command: &str) -> bool { + let output = match std::process::Command::new(command) + .arg("--version") + .output() + { + Ok(output) => output, + Err(e) => { + // CI is expected to support all of the commands + if is_ci() && cfg!(linux) { + panic!( + "expected command `{}` to be somewhere in PATH: {}", + command, e + ); + } + return false; + } + }; + if !output.status.success() { + panic!( + "expected command `{}` to be runnable, got error {}:\n\ + stderr:{}\n\ + stdout:{}\n", + command, + output.status, + String::from_utf8_lossy(&output.stderr), + String::from_utf8_lossy(&output.stdout) + ); + } + let stdout = String::from_utf8_lossy(&output.stdout); + println!( + "$ {command} --version +{}", + stdout + ); + if cfg!(target_os = "macos") && stdout.starts_with("GNU bash, version 3") { + return false; + } + + true +} + +#[cfg(unix)] +pub fn register_example(name: &str, shell: completest::Shell) { + let shell_name = shell.name(); + let home = std::path::Path::new("tests/snapshots/home") + .join(name) + .join(shell_name); + let bin_path = snapbox::cmd::compile_example(name, []).unwrap(); + let bin_root = bin_path.parent().unwrap().to_owned(); + + let registration = std::process::Command::new(&bin_path) + .arg(format!("--generate={shell_name}")) + .output() + .unwrap(); + assert!( + registration.status.success(), + "{}", + String::from_utf8_lossy(®istration.stderr) + ); + let registration = std::str::from_utf8(®istration.stdout).unwrap(); + assert!(!registration.is_empty()); + + let runtime = shell.init(bin_root, home).unwrap(); + + runtime.register(name, registration).unwrap(); +} + +#[cfg(unix)] +pub fn load_runtime(name: &str, shell: completest::Shell) -> Box { + let shell_name = shell.name(); + let home = std::path::Path::new("tests/snapshots/home") + .join(name) + .join(shell_name); + let bin_path = snapbox::cmd::compile_example(name, []).unwrap(); + let bin_root = bin_path.parent().unwrap().to_owned(); + + shell.with_home(bin_root, home) +} + +/// Whether or not this running in a Continuous Integration environment. +fn is_ci() -> bool { + // Consider using `tracked_env` instead of option_env! when it is stabilized. + // `tracked_env` will handle changes, but not require rebuilding the macro + // itself like option_env does. + option_env!("CI").is_some() || option_env!("TF_BUILD").is_some() +}