engine-q merge

This commit is contained in:
Fernando Herrera
2022-02-07 19:11:34 +00:00
1965 changed files with 119062 additions and 20 deletions

View File

@ -1,3 +1,4 @@
<<<<<<< HEAD
use nu_protocol::hir::{Expression, ExternalArgs, ExternalCommand, SpannedExpression};
use nu_source::{Span, SpannedItem, Tag};
@ -44,3 +45,58 @@ impl ExternalBuilder {
}
}
}
=======
// use nu_protocol::{
// ast::{Expr, Expression},
// Span, Spanned, Type,
// };
// pub struct ExternalBuilder {
// name: String,
// args: Vec<String>,
// }
// impl ExternalBuilder {
// pub fn for_name(name: &str) -> ExternalBuilder {
// ExternalBuilder {
// name: name.to_string(),
// args: vec![],
// }
// }
// pub fn arg(&mut self, value: &str) -> &mut Self {
// self.args.push(value.to_string());
// self
// }
// pub fn build(&mut self) -> ExternalCommand {
// let mut path = crate::fs::binaries();
// path.push(&self.name);
// let name = Spanned {
// item: path.to_string_lossy().to_string(),
// span: Span::new(0, 0),
// };
// let args = self
// .args
// .iter()
// .map(|arg| Expression {
// expr: Expr::String(arg.to_string()),
// span: Span::new(0, 0),
// ty: Type::Unknown,
// custom_completion: None,
// })
// .collect::<Vec<_>>();
// ExternalCommand {
// name: name.to_string(),
// name_tag: Tag::unknown(),
// args: ExternalArgs {
// list: args,
// span: name.span,
// },
// }
// }
// }
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce

View File

@ -1,277 +0,0 @@
use std::io::Read;
use std::ops::Div;
use std::path::{Path, PathBuf};
pub struct AbsoluteFile {
inner: PathBuf,
}
impl AbsoluteFile {
pub fn new(path: impl AsRef<Path>) -> AbsoluteFile {
let path = path.as_ref();
if !path.is_absolute() {
panic!(
"AbsoluteFile::new must take an absolute path :: {}",
path.display()
)
} else if path.is_dir() {
// At the moment, this is not an invariant, but rather a way to catch bugs
// in tests.
panic!(
"AbsoluteFile::new must not take a directory :: {}",
path.display()
)
} else {
AbsoluteFile {
inner: path.to_path_buf(),
}
}
}
pub fn dir(&self) -> AbsolutePath {
AbsolutePath::new(if let Some(parent) = self.inner.parent() {
parent
} else {
unreachable!("Internal error: could not get parent in dir")
})
}
}
impl From<AbsoluteFile> for PathBuf {
fn from(file: AbsoluteFile) -> Self {
file.inner
}
}
pub struct AbsolutePath {
pub inner: PathBuf,
}
impl AbsolutePath {
pub fn new(path: impl AsRef<Path>) -> AbsolutePath {
let path = path.as_ref();
if path.is_absolute() {
AbsolutePath {
inner: path.to_path_buf(),
}
} else {
panic!("AbsolutePath::new must take an absolute path")
}
}
}
impl Div<&str> for &AbsolutePath {
type Output = AbsolutePath;
fn div(self, rhs: &str) -> Self::Output {
let parts = rhs.split('/');
let mut result = self.inner.clone();
for part in parts {
result = result.join(part);
}
AbsolutePath::new(result)
}
}
impl AsRef<Path> for AbsolutePath {
fn as_ref(&self) -> &Path {
self.inner.as_path()
}
}
pub struct RelativePath {
inner: PathBuf,
}
impl RelativePath {
pub fn new(path: impl Into<PathBuf>) -> RelativePath {
let path = path.into();
if path.is_relative() {
RelativePath { inner: path }
} else {
panic!("RelativePath::new must take a relative path")
}
}
}
impl<T: AsRef<str>> Div<T> for &RelativePath {
type Output = RelativePath;
fn div(self, rhs: T) -> Self::Output {
let parts = rhs.as_ref().split('/');
let mut result = self.inner.clone();
for part in parts {
result = result.join(part);
}
RelativePath::new(result)
}
}
pub trait DisplayPath {
fn display_path(&self) -> String;
}
impl DisplayPath for AbsolutePath {
fn display_path(&self) -> String {
self.inner.display().to_string()
}
}
impl DisplayPath for PathBuf {
fn display_path(&self) -> String {
self.display().to_string()
}
}
impl DisplayPath for str {
fn display_path(&self) -> String {
self.to_string()
}
}
impl DisplayPath for &str {
fn display_path(&self) -> String {
(*self).to_string()
}
}
impl DisplayPath for String {
fn display_path(&self) -> String {
self.clone()
}
}
impl DisplayPath for &String {
fn display_path(&self) -> String {
(*self).to_string()
}
}
pub enum Stub<'a> {
FileWithContent(&'a str, &'a str),
FileWithContentToBeTrimmed(&'a str, &'a str),
EmptyFile(&'a str),
}
pub fn file_contents(full_path: impl AsRef<Path>) -> String {
let mut file = std::fs::File::open(full_path.as_ref()).expect("can not open file");
let mut contents = String::new();
file.read_to_string(&mut contents)
.expect("can not read file");
contents
}
pub fn file_contents_binary(full_path: impl AsRef<Path>) -> Vec<u8> {
let mut file = std::fs::File::open(full_path.as_ref()).expect("can not open file");
let mut contents = Vec::new();
file.read_to_end(&mut contents).expect("can not read file");
contents
}
pub fn line_ending() -> String {
#[cfg(windows)]
{
String::from("\r\n")
}
#[cfg(not(windows))]
{
String::from("\n")
}
}
pub fn delete_file_at(full_path: impl AsRef<Path>) {
let full_path = full_path.as_ref();
if full_path.exists() {
std::fs::remove_file(full_path).expect("can not delete file");
}
}
pub fn create_file_at(full_path: impl AsRef<Path>) -> Result<(), std::io::Error> {
let full_path = full_path.as_ref();
if full_path.parent().is_some() {
panic!("path exists");
}
std::fs::write(full_path, b"fake data")
}
pub fn copy_file_to(source: &str, destination: &str) {
std::fs::copy(source, destination).expect("can not copy file");
}
pub fn files_exist_at(files: Vec<impl AsRef<Path>>, path: impl AsRef<Path>) -> bool {
files.iter().all(|f| {
let mut loc = PathBuf::from(path.as_ref());
loc.push(f);
loc.exists()
})
}
pub fn delete_directory_at(full_path: &str) {
std::fs::remove_dir_all(PathBuf::from(full_path)).expect("can not remove directory");
}
pub fn executable_path() -> PathBuf {
let mut path = binaries();
path.push("nu");
path
}
pub fn root() -> PathBuf {
let manifest_dir = if let Ok(manifest_dir) = std::env::var("CARGO_MANIFEST_DIR") {
PathBuf::from(manifest_dir)
} else {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
};
let test_path = manifest_dir.join("Cargo.lock");
if test_path.exists() {
manifest_dir
} else {
manifest_dir
.parent()
.expect("Couldn't find the debug binaries directory")
.parent()
.expect("Couldn't find the debug binaries directory")
.to_path_buf()
}
}
pub fn binaries() -> PathBuf {
let mut build_type = "debug";
if !cfg!(debug_assertions) {
build_type = "release"
}
std::env::var("CARGO_TARGET_DIR")
.ok()
.map(|target_dir| PathBuf::from(target_dir).join(&build_type))
.unwrap_or_else(|| root().join(format!("target/{}", &build_type)))
}
pub fn fixtures() -> PathBuf {
root().join("tests/fixtures")
}
pub fn assets() -> PathBuf {
root().join("tests/assets")
}
pub fn in_directory(str: impl AsRef<Path>) -> String {
let path = str.as_ref();
let path = if path.is_relative() {
root().join(path)
} else {
path.to_path_buf()
};
path.display().to_string()
}

View File

@ -2,7 +2,10 @@ pub mod commands;
pub mod fs;
pub mod macros;
pub mod playground;
<<<<<<< HEAD
pub mod value;
=======
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
pub struct Outcome {
pub out: String,
@ -57,7 +60,11 @@ mod tests {
open los_tres_amigos.txt
| from-csv
| get rusty_luck
<<<<<<< HEAD
| str to-int
=======
| into int
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
| math sum
| echo "$it"
"#,
@ -65,7 +72,11 @@ mod tests {
assert_eq!(
actual,
<<<<<<< HEAD
r#"open los_tres_amigos.txt | from-csv | get rusty_luck | str to-int | math sum | echo "$it""#
=======
r#"open los_tres_amigos.txt | from-csv | get rusty_luck | into int | math sum | echo "$it""#
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
);
}
}

View File

@ -15,11 +15,16 @@ macro_rules! nu {
}};
($cwd:expr, $path:expr) => {{
<<<<<<< HEAD
=======
pub use itertools::Itertools;
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
pub use std::error::Error;
pub use std::io::prelude::*;
pub use std::process::{Command, Stdio};
pub use $crate::NATIVE_PATH_ENV_VAR;
<<<<<<< HEAD
let commands = &*format!(
"
cd \"{}\"
@ -31,6 +36,21 @@ macro_rules! nu {
let test_bins = $crate::fs::binaries();
let test_bins = nu_path::canonicalize(&test_bins).unwrap_or_else(|e| {
=======
// let commands = &*format!(
// "
// cd \"{}\"
// {}
// exit",
// $crate::fs::in_directory($cwd),
// $crate::fs::DisplayPath::display_path(&$path)
// );
let test_bins = $crate::fs::binaries();
let cwd = std::env::current_dir().expect("Could not get current working directory.");
let test_bins = nu_path::canonicalize_with(&test_bins, cwd).unwrap_or_else(|e| {
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
panic!(
"Couldn't canonicalize dummy binaries path {}: {:?}",
test_bins.display(),
@ -41,6 +61,11 @@ macro_rules! nu {
let mut paths = $crate::shell_os_paths();
paths.insert(0, test_bins);
<<<<<<< HEAD
=======
let path = $path.lines().collect::<Vec<_>>().join("; ");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
let paths_joined = match std::env::join_paths(paths) {
Ok(all) => all,
Err(_) => panic!("Couldn't join paths for PATH var."),
@ -48,16 +73,27 @@ macro_rules! nu {
let mut process = match Command::new($crate::fs::executable_path())
.env(NATIVE_PATH_ENV_VAR, paths_joined)
<<<<<<< HEAD
.arg("--skip-plugins")
.arg("--no-history")
.arg("--config-file")
.arg($crate::fs::DisplayPath::display_path(&$crate::fs::fixtures().join("playground/config/default.toml")))
.stdout(Stdio::piped())
.stdin(Stdio::piped())
=======
// .arg("--skip-plugins")
// .arg("--no-history")
// .arg("--config-file")
// .arg($crate::fs::DisplayPath::display_path(&$crate::fs::fixtures().join("playground/config/default.toml")))
.arg(format!("-c 'cd {}; {}'", $crate::fs::in_directory($cwd), $crate::fs::DisplayPath::display_path(&path)))
.stdout(Stdio::piped())
// .stdin(Stdio::piped())
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
.stderr(Stdio::piped())
.spawn()
{
Ok(child) => child,
<<<<<<< HEAD
Err(why) => panic!("Can't run test {}", why.to_string()),
};
@ -65,6 +101,15 @@ macro_rules! nu {
stdin
.write_all(commands.as_bytes())
.expect("couldn't write to stdin");
=======
Err(why) => panic!("Can't run test {:?} {}", $crate::fs::executable_path(), why.to_string()),
};
// let stdin = process.stdin.as_mut().expect("couldn't open stdin");
// stdin
// .write_all(b"exit\n")
// .expect("couldn't write to stdin");
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
let output = process
.wait_with_output()

View File

@ -1,12 +0,0 @@
mod director;
pub mod matchers;
pub mod nu_process;
mod play;
#[cfg(test)]
mod tests;
pub use director::Director;
pub use matchers::says;
pub use nu_process::{Executable, NuProcess, NuResult, Outcome};
pub use play::{Dirs, EnvironmentVariable, Playground};

View File

@ -84,22 +84,45 @@ impl Director {
impl Executable for Director {
fn execute(&mut self) -> NuResult {
<<<<<<< HEAD
use std::io::Write;
=======
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
use std::process::Stdio;
match self.executable() {
Some(binary) => {
<<<<<<< HEAD
let mut process = match binary
.construct()
.stdout(Stdio::piped())
.stdin(Stdio::piped())
.stderr(Stdio::piped())
=======
let mut commands = String::new();
if let Some(pipelines) = &self.pipeline {
for pipeline in pipelines {
if !commands.is_empty() {
commands.push_str("| ");
}
commands.push_str(&format!("{}\n", pipeline));
}
}
let process = match binary
.construct()
.stdout(Stdio::piped())
// .stdin(Stdio::piped())
.stderr(Stdio::piped())
.arg(format!("-c '{}'", commands))
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
.spawn()
{
Ok(child) => child,
Err(why) => panic!("Can't run test {}", why),
};
<<<<<<< HEAD
if let Some(pipelines) = &self.pipeline {
let child = process.stdin.as_mut().expect("Failed to open stdin");
@ -112,6 +135,8 @@ impl Executable for Director {
child.write_all(b"exit\n").expect("Could not write to");
}
=======
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
process
.wait_with_output()
.map_err(|_| {

View File

@ -1,105 +0,0 @@
use hamcrest2::core::{MatchResult, Matcher};
use std::fmt;
use std::str;
use super::nu_process::Outcome;
use super::{Director, Executable};
#[derive(Clone)]
pub struct Play {
stdout_expectation: Option<String>,
}
impl fmt::Display for Play {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "play")
}
}
impl fmt::Debug for Play {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "play")
}
}
pub fn says() -> Play {
Play {
stdout_expectation: None,
}
}
trait CheckerMatchers {
fn output(&self, actual: &Outcome) -> MatchResult;
fn std(&self, actual: &[u8], expected: Option<&String>, description: &str) -> MatchResult;
fn stdout(&self, actual: &Outcome) -> MatchResult;
}
impl CheckerMatchers for Play {
fn output(&self, actual: &Outcome) -> MatchResult {
self.stdout(actual)
}
fn stdout(&self, actual: &Outcome) -> MatchResult {
self.std(&actual.out, self.stdout_expectation.as_ref(), "stdout")
}
fn std(&self, actual: &[u8], expected: Option<&String>, description: &str) -> MatchResult {
let out = match expected {
Some(out) => out,
None => return Ok(()),
};
let actual = match str::from_utf8(actual) {
Err(..) => return Err(format!("{} was not utf8 encoded", description)),
Ok(actual) => actual,
};
if actual != *out {
return Err(format!(
"not equal:\n actual: {}\n expected: {}\n\n",
actual, out
));
}
Ok(())
}
}
impl Matcher<Outcome> for Play {
fn matches(&self, output: Outcome) -> MatchResult {
self.output(&output)
}
}
impl Matcher<Director> for Play {
fn matches(&self, mut director: Director) -> MatchResult {
self.matches(&mut director)
}
}
impl<'a> Matcher<&'a mut Director> for Play {
fn matches(&self, director: &'a mut Director) -> MatchResult {
if director.executable().is_none() {
return Err(format!("no such process {}", director));
}
let res = director.execute();
match res {
Ok(out) => self.output(&out),
Err(err) => {
if let Some(out) = &err.output {
return self.output(out);
}
Err(format!("could not exec process {}: {:?}", director, err))
}
}
}
}
impl Play {
pub fn stdout(mut self, expected: &str) -> Self {
self.stdout_expectation = Some(expected.to_string());
self
}
}

View File

@ -1,104 +0,0 @@
use super::EnvironmentVariable;
use crate::fs::{binaries as test_bins_path, executable_path};
use std::ffi::{OsStr, OsString};
use std::fmt;
use std::path::Path;
use std::process::{Command, ExitStatus};
pub trait Executable {
fn execute(&mut self) -> NuResult;
}
#[derive(Clone, Debug)]
pub struct Outcome {
pub out: Vec<u8>,
pub err: Vec<u8>,
}
impl Outcome {
pub fn new(out: &[u8], err: &[u8]) -> Outcome {
Outcome {
out: out.to_vec(),
err: err.to_vec(),
}
}
}
pub type NuResult = Result<Outcome, NuError>;
#[derive(Debug)]
pub struct NuError {
pub desc: String,
pub exit: Option<ExitStatus>,
pub output: Option<Outcome>,
}
#[derive(Clone, Debug, Default)]
pub struct NuProcess {
pub arguments: Vec<OsString>,
pub environment_vars: Vec<EnvironmentVariable>,
pub cwd: Option<OsString>,
}
impl fmt::Display for NuProcess {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "`nu")?;
for arg in &self.arguments {
write!(f, " {}", arg.to_string_lossy())?;
}
write!(f, "`")
}
}
impl NuProcess {
pub fn arg<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut Self {
self.arguments.push(arg.as_ref().to_os_string());
self
}
pub fn args<T: AsRef<OsStr>>(&mut self, arguments: &[T]) -> &mut NuProcess {
self.arguments
.extend(arguments.iter().map(|t| t.as_ref().to_os_string()));
self
}
pub fn cwd<T: AsRef<OsStr>>(&mut self, path: T) -> &mut NuProcess {
self.cwd = Some(path.as_ref().to_os_string());
self
}
pub fn get_cwd(&self) -> Option<&Path> {
self.cwd.as_ref().map(Path::new)
}
pub fn construct(&self) -> Command {
let mut command = Command::new(&executable_path());
if let Some(cwd) = self.get_cwd() {
command.current_dir(cwd);
}
command.env_clear();
let paths = vec![test_bins_path()];
let paths_joined = match std::env::join_paths(&paths) {
Ok(all) => all,
Err(_) => panic!("Couldn't join paths for PATH var."),
};
command.env(crate::NATIVE_PATH_ENV_VAR, paths_joined);
for env_var in &self.environment_vars {
command.env(&env_var.name, &env_var.value);
}
for arg in &self.arguments {
command.arg(arg);
}
command
}
}

View File

@ -78,7 +78,12 @@ impl<'a> Playground<'a> {
std::fs::create_dir(PathBuf::from(&nuplay_dir)).expect("can not create directory");
let fixtures = fs::fixtures();
<<<<<<< HEAD
let fixtures = nu_path::canonicalize(fixtures.clone()).unwrap_or_else(|e| {
=======
let cwd = std::env::current_dir().expect("Could not get current working directory.");
let fixtures = nu_path::canonicalize_with(fixtures.clone(), cwd).unwrap_or_else(|e| {
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
panic!(
"Couldn't canonicalize fixtures path {}: {:?}",
fixtures.display(),
@ -97,6 +102,7 @@ impl<'a> Playground<'a> {
let playground_root = playground.root.path();
<<<<<<< HEAD
let test = nu_path::canonicalize(playground_root.join(topic)).unwrap_or_else(|e| {
panic!(
"Couldn't canonicalize test path {}: {:?}",
@ -106,6 +112,20 @@ impl<'a> Playground<'a> {
});
let root = nu_path::canonicalize(playground_root).unwrap_or_else(|e| {
=======
let cwd = std::env::current_dir().expect("Could not get current working directory.");
let test =
nu_path::canonicalize_with(playground_root.join(topic), cwd).unwrap_or_else(|e| {
panic!(
"Couldn't canonicalize test path {}: {:?}",
playground_root.join(topic).display(),
e
)
});
let cwd = std::env::current_dir().expect("Could not get current working directory.");
let root = nu_path::canonicalize_with(playground_root, cwd).unwrap_or_else(|e| {
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
panic!(
"Couldn't canonicalize tests root path {}: {:?}",
playground_root.display(),

View File

@ -1,16 +1,23 @@
use crate::playground::Playground;
use std::path::{Path, PathBuf};
<<<<<<< HEAD
use super::matchers::says;
use hamcrest2::assert_that;
use hamcrest2::prelude::*;
fn path(p: &Path) -> PathBuf {
nu_path::canonicalize(p)
=======
fn path(p: &Path) -> PathBuf {
let cwd = std::env::current_dir().expect("Could not get current working directory.");
nu_path::canonicalize_with(p, cwd)
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
.unwrap_or_else(|e| panic!("Couldn't canonicalize path {}: {:?}", p.display(), e))
}
#[test]
<<<<<<< HEAD
fn asserts_standard_out_expectation_from_nu_executable() {
Playground::setup("topic", |_, nu| {
assert_that!(nu.cococo("andres"), says().stdout("andres"));
@ -25,6 +32,8 @@ fn asserts_standard_out_expectation_from_nu_executable_pipeline_fed() {
}
#[test]
=======
>>>>>>> 9259a56a28f1dd3a4b720ad815aa19c6eaf6adce
fn current_working_directory_in_sandbox_directory_created() {
Playground::setup("topic", |dirs, nu| {
let original_cwd = dirs.test();

View File

@ -1,61 +0,0 @@
use bigdecimal::BigDecimal;
use chrono::{DateTime, NaiveDate, Utc};
use indexmap::IndexMap;
use nu_errors::ShellError;
use nu_protocol::{PathMember, Primitive, UntaggedValue, Value};
use nu_source::{Span, TaggedItem};
use num_bigint::BigInt;
pub fn big_int(s: impl Into<BigInt>) -> Value {
UntaggedValue::big_int(s).into_untagged_value()
}
pub fn int(s: impl Into<i64>) -> Value {
UntaggedValue::int(s).into_untagged_value()
}
pub fn decimal(s: BigDecimal) -> Value {
UntaggedValue::Primitive(Primitive::Decimal(s)).into_untagged_value()
}
pub fn decimal_from_float(f: f64) -> Value {
UntaggedValue::decimal_from_float(f, Span::unknown()).into_untagged_value()
}
pub fn string(input: impl Into<String>) -> Value {
UntaggedValue::string(input.into()).into_untagged_value()
}
pub fn row(entries: IndexMap<String, Value>) -> Value {
UntaggedValue::row(entries).into_untagged_value()
}
pub fn nothing() -> Value {
UntaggedValue::nothing().into_untagged_value()
}
pub fn table(list: &[Value]) -> Value {
UntaggedValue::table(list).into_untagged_value()
}
pub fn date(input: impl Into<String>) -> Value {
let key = input.into().tagged_unknown();
let date = NaiveDate::parse_from_str(key.borrow_tagged().item, "%Y-%m-%d")
.expect("date from string failed");
UntaggedValue::Primitive(Primitive::Date(
DateTime::<Utc>::from_utc(date.and_hms(12, 34, 56), Utc).into(),
))
.into_untagged_value()
}
pub fn column_path(paths: &str) -> Value {
UntaggedValue::column_path(paths, Span::unknown()).into_untagged_value()
}
pub fn error_callback(
reason: &'static str,
) -> impl FnOnce(&Value, &PathMember, ShellError) -> ShellError {
move |_obj_source, _column_path_tried, _err| ShellError::unimplemented(reason)
}