Groundwork for coverage with Nu internals. (#1205)

This commit is contained in:
Andrés N. Robalino 2020-01-12 16:44:22 -05:00 committed by GitHub
parent 5fd3191d91
commit d3dae05714
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 190 additions and 17 deletions

View file

@ -42,16 +42,16 @@ steps:
echo "##vso[task.prependpath]$HOME/.cargo/bin"
rustup component add rustfmt --toolchain "stable"
displayName: Install Rust
- bash: RUSTFLAGS="-D warnings" cargo test --all --features=stable
- bash: RUSTFLAGS="-D warnings" cargo test --all --features=stable,nu-dummies
condition: eq(variables['style'], 'unflagged')
displayName: Run tests
- bash: RUSTFLAGS="-D warnings" cargo clippy --all --features=stable -- -D clippy::result_unwrap_used -D clippy::option_unwrap_used
- bash: RUSTFLAGS="-D warnings" cargo clippy --all --features=stable,nu-dummies -- -D clippy::result_unwrap_used -D clippy::option_unwrap_used
condition: eq(variables['style'], 'unflagged')
displayName: Check clippy lints
- bash: NUSHELL_ENABLE_ALL_FLAGS=1 RUSTFLAGS="-D warnings" cargo test --all --features=stable
- bash: NUSHELL_ENABLE_ALL_FLAGS=1 RUSTFLAGS="-D warnings" cargo test --all --features=stable,nu-dummies
condition: eq(variables['style'], 'canary')
displayName: Run tests
- bash: NUSHELL_ENABLE_ALL_FLAGS=1 RUSTFLAGS="-D warnings" cargo clippy --all --features=stable -- -D clippy::result_unwrap_used -D clippy::option_unwrap_used
- bash: NUSHELL_ENABLE_ALL_FLAGS=1 RUSTFLAGS="-D warnings" cargo clippy --all --features=stable,nu-dummies -- -D clippy::result_unwrap_used -D clippy::option_unwrap_used
condition: eq(variables['style'], 'canary')
displayName: Check clippy lints
- bash: cargo fmt --all -- --check

View file

@ -142,6 +142,8 @@ users = "0.9"
default = ["sys", "ps", "textview", "inc", "str"]
stable = ["sys", "ps", "textview", "inc", "str", "starship-prompt", "binaryview", "match", "tree", "average", "sum", "post", "fetch", "clipboard"]
nu-dummies = []
# Default
sys = ["heim", "battery"]
ps = ["heim", "futures-timer"]
@ -178,6 +180,21 @@ name = "nu"
doctest = false
path = "src/lib.rs"
[[bin]]
name = "fail"
path = "crates/nu-test-support/src/bin/fail.rs"
required-features = ["nu-dummies"]
[[bin]]
name = "chop"
path = "crates/nu-test-support/src/bin/chop.rs"
required-features = ["nu-dummies"]
[[bin]]
name = "cococo"
path = "crates/nu-test-support/src/bin/cococo.rs"
required-features = ["nu-dummies"]
# Core plugins that ship with `cargo install nu` by default
# Currently, Cargo limits us to installing only one binary
# unless we use [[bin]], so we use this as a workaround

View file

@ -0,0 +1,22 @@
use std::io::{self, BufRead};
fn main() {
let stdin = io::stdin();
let mut input = stdin.lock().lines();
if let Some(Ok(given)) = input.next() {
if !given.is_empty() {
println!("{}", chop(&given));
std::process::exit(0);
}
}
std::process::exit(0);
}
fn chop(word: &str) -> &str {
let to = word.len() - 1;
&word[..to]
}

View file

@ -0,0 +1,17 @@
fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() > 1 {
// Write back out all the arguments passed
// if given at least 1 instead of chickens
// speaking co co co.
let mut arguments = args.iter();
arguments.next();
for arg in arguments {
println!("{}", &arg);
}
} else {
println!("cococo");
}
}

View file

@ -0,0 +1,3 @@
fn main() {
std::process::exit(1);
}

View file

@ -220,11 +220,16 @@ pub fn delete_directory_at(full_path: &str) {
}
pub fn executable_path() -> PathBuf {
let mut buf = PathBuf::new();
buf.push("target");
buf.push("debug");
buf.push("nu");
buf
let mut path = binaries();
path.push("nu");
path
}
pub fn binaries() -> PathBuf {
let mut path = PathBuf::new();
path.push("target");
path.push("debug");
path
}
pub fn in_directory(str: impl AsRef<Path>) -> String {

View file

@ -13,7 +13,7 @@ pub fn pipeline(commands: &str) -> String {
.to_string()
}
#[cfg(tests)]
#[cfg(test)]
mod tests {
use super::pipeline;

View file

@ -159,6 +159,17 @@ async fn run_with_iterator_arg(
}
}
pub fn argument_is_quoted(argument: &str) -> bool {
(argument.starts_with('"') && argument.ends_with('"')
|| (argument.starts_with('\'') && argument.ends_with('\'')))
}
pub fn remove_quotes(argument: &str) -> &str {
let size = argument.len();
&argument[1..size - 1]
}
async fn run_with_stdin(
command: ExternalCommand,
context: &mut Context,
@ -169,19 +180,17 @@ async fn run_with_stdin(
let home_dir = dirs::home_dir();
let mut process = Exec::cmd(&command.name);
for arg in command.args.iter() {
// Let's also replace ~ as we shell out
let arg = shellexpand::tilde_with_context(arg.deref(), || home_dir.as_ref());
// Strip quotes from a quoted string
if arg.len() > 1
&& ((arg.starts_with('"') && arg.ends_with('"'))
|| (arg.starts_with('\'') && arg.ends_with('\'')))
{
process = process.arg(arg.chars().skip(1).take(arg.len() - 2).collect::<String>());
process = if arg.len() > 1 && (argument_is_quoted(&arg)) {
process.arg(remove_quotes(&arg))
} else {
process = process.arg(arg.as_ref());
}
process.arg(arg.as_ref())
};
}
process = process.cwd(context.shell_manager.path()?);
@ -315,3 +324,103 @@ async fn run_with_stdin(
))
}
}
#[cfg(test)]
mod tests {
use super::{argument_is_quoted, remove_quotes, run_external_command, Context, OutputStream};
use futures::executor::block_on;
use futures::stream::TryStreamExt;
use nu_errors::ShellError;
use nu_parser::commands::classified::external::{ExternalArgs, ExternalCommand};
use nu_protocol::{UntaggedValue, Value};
use nu_source::{Span, SpannedItem, Tag};
async fn read(mut stream: OutputStream) -> Option<Value> {
match stream.try_next().await {
Ok(val) => {
if let Some(val) = val {
val.raw_value()
} else {
None
}
}
Err(_) => None,
}
}
fn external(name: &str) -> ExternalCommand {
let mut path = nu_test_support::fs::binaries();
path.push(name);
let name = path.to_string_lossy().to_string().spanned(Span::unknown());
ExternalCommand {
name: name.to_string(),
name_tag: Tag {
anchor: None,
span: name.span,
},
args: ExternalArgs {
list: vec![],
span: name.span,
},
}
}
async fn non_existent_run() -> Result<(), ShellError> {
let cmd = external("i_dont_exist.exe");
let mut ctx = Context::basic().expect("There was a problem creating a basic context.");
assert!(run_external_command(cmd, &mut ctx, None, false)
.await
.is_err());
Ok(())
}
async fn failure_run() -> Result<(), ShellError> {
let cmd = external("fail");
let mut ctx = Context::basic().expect("There was a problem creating a basic context.");
let stream = run_external_command(cmd, &mut ctx, None, false)
.await?
.expect("There was a problem running the external command.");
match read(stream.into()).await {
Some(Value {
value: UntaggedValue::Error(_),
..
}) => {}
None | _ => panic!("Command didn't fail."),
}
Ok(())
}
#[test]
fn identifies_command_failed() -> Result<(), ShellError> {
block_on(failure_run())
}
#[test]
fn identifies_command_not_found() -> Result<(), ShellError> {
block_on(non_existent_run())
}
#[test]
fn checks_quotes_from_argument_to_be_passed_in() {
assert_eq!(argument_is_quoted("'andrés"), false);
assert_eq!(argument_is_quoted("andrés'"), false);
assert_eq!(argument_is_quoted(r#""andrés"#), false);
assert_eq!(argument_is_quoted(r#"andrés""#), false);
assert_eq!(argument_is_quoted("'andrés'"), true);
assert_eq!(argument_is_quoted(r#""andrés""#), true);
}
#[test]
fn strips_quotes_from_argument_to_be_passed_in() {
assert_eq!(remove_quotes(r#"'andrés'"#), "andrés");
assert_eq!(remove_quotes(r#""andrés""#), "andrés");
}
}