diff --git a/Cargo.lock b/Cargo.lock index ecfc25c73c1..13063f9911c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3121,8 +3121,11 @@ checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" dependencies = [ "anstyle", "difflib", + "float-cmp", "itertools", + "normalize-line-endings", "predicates-core", + "regex", ] [[package]] @@ -5632,6 +5635,7 @@ name = "wasmer-cli" version = "4.0.0-beta.3" dependencies = [ "anyhow", + "assert_cmd 2.0.11", "async-trait", "atty", "bytes", @@ -5653,6 +5657,7 @@ dependencies = [ "object 0.30.4", "once_cell", "pathdiff", + "predicates 3.0.3", "prettytable-rs", "regex", "reqwest", diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index d8674d5bbf9..9c5e00c8556 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -125,84 +125,33 @@ unix_mode = "0.1.3" [features] # Don't add the compiler features in default, please add them on the Makefile # since we might want to autoconfigure them depending on the availability on the host. -default = [ - "sys", - "wat", - "wast", - "compiler", - "wasmer-artifact-create", - "static-artifact-create", -] +default = ["sys", "wat", "wast", "compiler", "wasmer-artifact-create", "static-artifact-create"] backend = [] -coredump = [ - "wasm-coredump-builder", -] -sys = [ - "compiler", - "wasmer-vm", -] -jsc = [ - "backend", - "wasmer/jsc", - "wasmer/std" -] +coredump = ["wasm-coredump-builder"] +sys = ["compiler", "wasmer-vm"] +jsc = ["backend", "wasmer/jsc", "wasmer/std"] wast = ["wasmer-wast"] -host-net = [ "virtual-net/host-net" ] +host-net = ["virtual-net/host-net"] wat = ["wasmer/wat"] -compiler = [ - "backend", - "wasmer/compiler", - "wasmer-compiler/translator", - "wasmer-compiler/compiler" -] -wasmer-artifact-create = ["compiler", - "wasmer/wasmer-artifact-load", - "wasmer/wasmer-artifact-create", - "wasmer-compiler/wasmer-artifact-load", - "wasmer-compiler/wasmer-artifact-create", - "wasmer-object", - ] -static-artifact-create = ["compiler", - "wasmer/static-artifact-load", - "wasmer/static-artifact-create", - "wasmer-compiler/static-artifact-load", - "wasmer-compiler/static-artifact-create", - "wasmer-object", - ] -wasmer-artifact-load = ["compiler", - "wasmer/wasmer-artifact-load", - "wasmer-compiler/wasmer-artifact-load", - ] -static-artifact-load = ["compiler", - "wasmer/static-artifact-load", - "wasmer-compiler/static-artifact-load", - ] -experimental-io-devices = [ - "wasmer-wasix-experimental-io-devices", -] -singlepass = [ - "wasmer-compiler-singlepass", - "compiler", -] -cranelift = [ - "wasmer-compiler-cranelift", - "compiler", -] -llvm = [ - "wasmer-compiler-llvm", - "compiler", -] +compiler = ["backend", "wasmer/compiler", "wasmer-compiler/translator", "wasmer-compiler/compiler"] +wasmer-artifact-create = ["compiler", "wasmer/wasmer-artifact-load", "wasmer/wasmer-artifact-create", "wasmer-compiler/wasmer-artifact-load", "wasmer-compiler/wasmer-artifact-create", "wasmer-object"] +static-artifact-create = ["compiler", "wasmer/static-artifact-load", "wasmer/static-artifact-create", "wasmer-compiler/static-artifact-load", "wasmer-compiler/static-artifact-create", "wasmer-object"] +wasmer-artifact-load = ["compiler", "wasmer/wasmer-artifact-load", "wasmer-compiler/wasmer-artifact-load"] +static-artifact-load = ["compiler", "wasmer/static-artifact-load", "wasmer-compiler/static-artifact-load"] +experimental-io-devices = ["wasmer-wasix-experimental-io-devices"] +singlepass = ["wasmer-compiler-singlepass", "compiler"] +cranelift = ["wasmer-compiler-cranelift", "compiler"] +llvm = ["wasmer-compiler-llvm", "compiler"] disable-all-logging = ["wasmer-wasix/disable-all-logging", "log/release_max_level_off"] headless = [] headless-minimal = ["headless", "disable-all-logging"] # Optional -enable-serde = [ - "wasmer/enable-serde", - "wasmer-vm/enable-serde", - "wasmer-compiler/enable-serde", - "wasmer-wasix/enable-serde", -] +enable-serde = ["wasmer/enable-serde", "wasmer-vm/enable-serde", "wasmer-compiler/enable-serde", "wasmer-wasix/enable-serde"] + +[dev-dependencies] +assert_cmd = "2.0.11" +predicates = "3.0.3" [target.'cfg(target_os = "windows")'.dependencies] colored = "2.0.0" diff --git a/lib/cli/src/cli.rs b/lib/cli/src/cli.rs index 833fa04a094..fcc3bd9ae67 100644 --- a/lib/cli/src/cli.rs +++ b/lib/cli/src/cli.rs @@ -35,12 +35,18 @@ fn wasmer_main_inner() -> Result<(), anyhow::Error> { args.output.initialize_logging(); args.execute() } - Err(e) if e.kind() == clap::error::ErrorKind::InvalidSubcommand => { - // Try to parse it as `wasmer some/package` - crate::logging::Output::default().initialize_logging(); - Run::parse().execute() - } Err(e) => { + if e.kind() == clap::error::ErrorKind::InvalidSubcommand { + if let Ok(run) = Run::try_parse() { + // Try to parse the command using the `wasmer some/package` + // shorthand. Note that this has discoverability issues + // because it's not shown as part of the main argument + // parser's help, but that's fine. + crate::logging::Output::default().initialize_logging(); + run.execute(); + } + } + e.exit(); } } @@ -48,9 +54,16 @@ fn wasmer_main_inner() -> Result<(), anyhow::Error> { /// Command-line arguments for the Wasmer CLI. #[derive(Parser, Debug)] -#[clap(about, author)] -#[cfg_attr(feature = "headless", clap(name = "wasmer-headless"))] -#[cfg_attr(not(feature = "headless"), clap(name = "wasmer-headless"))] +#[clap(author, version)] +#[clap(disable_version_flag = true)] // handled manually +#[cfg_attr(feature = "headless", clap( + name = "wasmer-headless", + about = concat!("wasmer-headless ", env!("CARGO_PKG_VERSION")), +))] +#[cfg_attr(not(feature = "headless"), clap( + name = "wasmer", + about = concat!("wasmer ", env!("CARGO_PKG_VERSION")), +))] pub struct Args { /// Print version info and exit. #[clap(short = 'V', long)] diff --git a/lib/cli/tests/version.rs b/lib/cli/tests/version.rs new file mode 100644 index 00000000000..1dcb7e83079 --- /dev/null +++ b/lib/cli/tests/version.rs @@ -0,0 +1,68 @@ +use assert_cmd::Command; + +const WASMER_VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[test] +fn short_version_string() { + let version_number = format!("wasmer {WASMER_VERSION}"); + + Command::cargo_bin("wasmer") + .unwrap() + .arg("--version") + .assert() + .success() + .stdout(predicates::str::contains(&version_number)); + + Command::cargo_bin("wasmer") + .unwrap() + .arg("-V") + .assert() + .success() + .stdout(predicates::str::contains(&version_number)); +} + +#[test] +fn long_version_string() { + let long_version_number = format!( + "wasmer {} ({} {})", + env!("CARGO_PKG_VERSION"), + env!("WASMER_BUILD_GIT_HASH_SHORT"), + env!("WASMER_BUILD_DATE") + ); + + Command::cargo_bin("wasmer") + .unwrap() + .arg("--version") + .arg("--verbose") + .assert() + .success() + .stdout(predicates::str::contains(&long_version_number)) + .stdout(predicates::str::contains("binary:")); + + Command::cargo_bin("wasmer") + .unwrap() + .arg("-Vv") + .assert() + .success() + .stdout(predicates::str::contains(&long_version_number)) + .stdout(predicates::str::contains("binary:")); +} + +#[test] +fn help_text_contains_version() { + let version_number = format!("wasmer {WASMER_VERSION}"); + + Command::cargo_bin("wasmer") + .unwrap() + .arg("-h") + .assert() + .success() + .stdout(predicates::str::contains(&version_number)); + + Command::cargo_bin("wasmer") + .unwrap() + .arg("--help") + .assert() + .success() + .stdout(predicates::str::contains(&version_number)); +} diff --git a/tests/integration/cli/tests/version.rs b/tests/integration/cli/tests/version.rs deleted file mode 100644 index f304749d732..00000000000 --- a/tests/integration/cli/tests/version.rs +++ /dev/null @@ -1,64 +0,0 @@ -use anyhow::bail; -use std::process::Command; -use wasmer_integration_tests_cli::get_wasmer_path; - -const WASMER_VERSION: &str = env!("CARGO_PKG_VERSION"); - -#[test] -fn version_string_is_correct() -> anyhow::Result<()> { - let expected_version_output = format!("wasmer {}\n", WASMER_VERSION); - let wasmer_path = get_wasmer_path(); - - let outputs = [ - Command::new(&wasmer_path).arg("--version").output()?, - Command::new(&wasmer_path).arg("-V").output()?, - ]; - - for output in &outputs { - if !output.status.success() { - bail!( - "version failed with: stdout: {}\n\nstderr: {}", - std::str::from_utf8(&output.stdout) - .expect("stdout is not utf8! need to handle arbitrary bytes"), - std::str::from_utf8(&output.stderr) - .expect("stderr is not utf8! need to handle arbitrary bytes") - ); - } - - let stdout_output = std::str::from_utf8(&output.stdout).unwrap(); - assert_eq!(stdout_output, &expected_version_output); - } - - Ok(()) -} - -#[test] -fn help_text_contains_version() -> anyhow::Result<()> { - let expected_version_output = format!("wasmer {}", WASMER_VERSION); - let wasmer_path = get_wasmer_path(); - - let outputs = [ - Command::new(&wasmer_path).arg("--help").output()?, - Command::new(&wasmer_path).arg("-h").output()?, - ]; - - for output in &outputs { - if !output.status.success() { - bail!( - "version failed with: stdout: {}\n\nstderr: {}", - std::str::from_utf8(&output.stdout) - .expect("stdout is not utf8! need to handle arbitrary bytes"), - std::str::from_utf8(&output.stderr) - .expect("stderr is not utf8! need to handle arbitrary bytes") - ); - } - - let stdout_output = std::str::from_utf8(&output.stdout).unwrap(); - assert_eq!( - stdout_output.lines().next().unwrap(), - &expected_version_output - ); - } - - Ok(()) -}