diff --git a/crates/nu-test-support/src/commands.rs b/crates/nu-test-support/src/commands.rs index d59c2f3dad..0206c5792b 100644 --- a/crates/nu-test-support/src/commands.rs +++ b/crates/nu-test-support/src/commands.rs @@ -51,3 +51,47 @@ // } // } // } + +use std::{ + io::Read, + process::{Command, Stdio}, +}; + +pub fn ensure_binary_present(package: &str) { + let cargo_path = env!("CARGO"); + let mut arguments = vec!["build", "--package", package, "--quiet"]; + + let profile = std::env::var("NUSHELL_CARGO_TARGET"); + if let Ok(profile) = &profile { + arguments.push("--profile"); + arguments.push(profile); + } + + let mut command = Command::new(cargo_path) + .args(arguments) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .expect("Failed to spawn cargo build command"); + + let stderr = command.stderr.take(); + + let success = command + .wait() + .expect("failed to wait cargo build command") + .success(); + + if let Some(mut stderr) = stderr { + let mut buffer = String::new(); + stderr + .read_to_string(&mut buffer) + .expect("failed to read cargo build stderr"); + if !buffer.is_empty() { + println!("=== cargo build stderr\n{}", buffer); + } + } + + if !success { + panic!("cargo build failed"); + } +} diff --git a/crates/nu-test-support/src/macros.rs b/crates/nu-test-support/src/macros.rs index 4df7bda7f9..1f1768ffc3 100644 --- a/crates/nu-test-support/src/macros.rs +++ b/crates/nu-test-support/src/macros.rs @@ -102,37 +102,38 @@ macro_rules! nu { }}; } +#[macro_export] +macro_rules! with_exe { + ($name:literal) => {{ + #[cfg(windows)] + { + concat!($name, ".exe") + } + #[cfg(not(windows))] + { + $name + } + }}; +} + #[macro_export] macro_rules! nu_with_plugins { - (cwd: $cwd:expr, $path:expr, $($part:expr),*) => {{ - use $crate::fs::DisplayPath; - - let path = format!($path, $( - $part.display_path() - ),*); - - nu_with_plugins!($cwd, &path) + (cwd: $cwd:expr, plugins: [$(($format:expr, $plugin_name:expr)),+$(,)?], $command:expr) => {{ + nu_with_plugins!($cwd, [$(($format, $plugin_name)),+], $command) + }}; + (cwd: $cwd:expr, plugin: ($format:expr, $plugin_name:expr), $command:expr) => {{ + nu_with_plugins!($cwd, [($format, $plugin_name)], $command) }}; - (cwd: $cwd:expr, $path:expr) => {{ - nu_with_plugins!($cwd, $path) - }}; - - ($cwd:expr, $path:expr) => {{ + ($cwd:expr, [$(($format:expr, $plugin_name:expr)),+$(,)?], $command:expr) => {{ pub use std::error::Error; pub use std::io::prelude::*; pub use std::process::{Command, Stdio}; - pub use $crate::NATIVE_PATH_ENV_VAR; - - let commands = &*format!( - " - {} - exit", - $crate::fs::DisplayPath::display_path(&$path) - ); + pub use tempfile::tempdir; + pub use $crate::{NATIVE_PATH_ENV_VAR, with_exe}; let test_bins = $crate::fs::binaries(); - let test_bins = nu_path::canonicalize(&test_bins).unwrap_or_else(|e| { + let test_bins = nu_path::canonicalize_with(&test_bins, ".").unwrap_or_else(|e| { panic!( "Couldn't canonicalize dummy binaries path {}: {:?}", test_bins.display(), @@ -140,21 +141,33 @@ macro_rules! nu_with_plugins { ) }); - let mut paths = $crate::shell_os_paths(); - paths.insert(0, test_bins); + let temp = tempdir().expect("couldn't create a temporary directory"); + let temp_plugin_file = temp.path().join("plugin.nu"); + std::fs::File::create(&temp_plugin_file).expect("couldn't create temporary plugin file"); - let paths_joined = match std::env::join_paths(paths) { - Ok(all) => all, - Err(_) => panic!("Couldn't join paths for PATH var."), - }; + $($crate::commands::ensure_binary_present($plugin_name);)+ + + let registrations = format!( + concat!($(concat!("register -e ", $format, " {};")),+), + $( + nu_path::canonicalize_with(with_exe!($plugin_name), &test_bins) + .unwrap_or_else(|e| { + panic!("failed to canonicalize plugin {} path", $plugin_name) + }) + .display() + ),+ + ); + let commands = format!("{registrations}{}", $command); let target_cwd = $crate::fs::in_directory(&$cwd); - let mut process = match Command::new($crate::fs::executable_path()) - .env("PWD", &target_cwd) // setting PWD is enough to set cwd - .env(NATIVE_PATH_ENV_VAR, paths_joined) + .current_dir(&target_cwd) + .env("PWD", &target_cwd) // setting PWD is enough to set cwd + .arg("--commands") + .arg(commands) + .arg("--plugin-config") + .arg(temp_plugin_file) .stdout(Stdio::piped()) - .stdin(Stdio::piped()) .stderr(Stdio::piped()) .spawn() { @@ -162,13 +175,6 @@ macro_rules! nu_with_plugins { Err(why) => panic!("Can't run test {}", why.to_string()), }; - let stdin = process.stdin.as_mut().expect("couldn't open stdin"); - stdin - .write_all(commands.as_bytes()) - .expect("couldn't write to stdin"); - - stdin.flush()? - let output = process .wait_with_output() .expect("couldn't read from stdout/stderr"); @@ -176,9 +182,9 @@ macro_rules! nu_with_plugins { let out = $crate::macros::read_std(&output.stdout); let err = String::from_utf8_lossy(&output.stderr); - println!("=== stderr\n{}", err); + println!("=== stderr\n{}", err); - $crate::Outcome::new(out,err.into_owned()) + $crate::Outcome::new(out, err.into_owned()) }}; } diff --git a/tests/main.rs b/tests/main.rs index 5630ea8968..004beaa7c4 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -5,6 +5,7 @@ mod nu_repl; mod overlays; mod parsing; mod path; +#[cfg(feature = "plugin")] mod plugins; mod scope; mod shell; diff --git a/tests/plugins/core_inc.rs b/tests/plugins/core_inc.rs index af7e261434..5811f24865 100644 --- a/tests/plugins/core_inc.rs +++ b/tests/plugins/core_inc.rs @@ -3,15 +3,23 @@ use nu_test_support::nu_with_plugins; use nu_test_support::playground::Playground; #[test] -fn can_only_apply_one() { +fn chooses_highest_increment_if_given_more_than_one() { let actual = nu_with_plugins!( cwd: "tests/fixtures/formats", - "open cargo_sample.toml | first 1 | inc package.version --major --minor" + plugin: ("json", "nu_plugin_inc"), + "open cargo_sample.toml | first 1 | inc package.version --major --minor | get package.version" ); - assert!(actual - .err - .contains("Usage: inc field [--major|--minor|--patch]")); + assert_eq!(actual.out, "1.0.0"); + + let actual = nu_with_plugins!( + cwd: "tests/fixtures/formats", + plugin: ("json", "nu_plugin_inc"), + // Regardless of order of arguments + "open cargo_sample.toml | first 1 | inc package.version --minor --major | get package.version" + ); + + assert_eq!(actual.out, "1.0.0"); } #[test] @@ -27,6 +35,7 @@ fn by_one_with_field_passed() { let actual = nu_with_plugins!( cwd: dirs.test(), + plugin: ("json", "nu_plugin_inc"), "open sample.toml | inc package.edition | get package.edition" ); @@ -47,6 +56,7 @@ fn by_one_with_no_field_passed() { let actual = nu_with_plugins!( cwd: dirs.test(), + plugin: ("json", "nu_plugin_inc"), "open sample.toml | get package.contributors | inc" ); @@ -67,6 +77,7 @@ fn semversion_major_inc() { let actual = nu_with_plugins!( cwd: dirs.test(), + plugin: ("json", "nu_plugin_inc"), "open sample.toml | inc package.version -M | get package.version" ); @@ -87,6 +98,7 @@ fn semversion_minor_inc() { let actual = nu_with_plugins!( cwd: dirs.test(), + plugin: ("json", "nu_plugin_inc"), "open sample.toml | inc package.version --minor | get package.version" ); @@ -107,6 +119,7 @@ fn semversion_patch_inc() { let actual = nu_with_plugins!( cwd: dirs.test(), + plugin: ("json", "nu_plugin_inc"), "open sample.toml | inc package.version --patch | get package.version" ); @@ -127,6 +140,7 @@ fn semversion_without_passing_field() { let actual = nu_with_plugins!( cwd: dirs.test(), + plugin: ("json", "nu_plugin_inc"), "open sample.toml | get package.version | inc --patch" ); diff --git a/tests/plugins/mod.rs b/tests/plugins/mod.rs index 23310d10ba..e3d59b2205 100644 --- a/tests/plugins/mod.rs +++ b/tests/plugins/mod.rs @@ -1,2 +1 @@ -#[cfg(features = "inc")] mod core_inc;