2019-07-17 21:51:18 +02:00
|
|
|
#![allow(dead_code)]
|
|
|
|
|
2019-08-01 23:00:08 +02:00
|
|
|
use glob::glob;
|
|
|
|
pub use std::path::Path;
|
2019-07-17 21:51:18 +02:00
|
|
|
pub use std::path::PathBuf;
|
2019-07-16 12:28:55 +02:00
|
|
|
|
2019-07-21 09:08:05 +02:00
|
|
|
use std::io::Read;
|
|
|
|
|
2019-07-17 20:56:15 +02:00
|
|
|
#[macro_export]
|
2019-07-16 12:28:55 +02:00
|
|
|
macro_rules! nu {
|
|
|
|
($out:ident, $cwd:expr, $commands:expr) => {
|
2019-07-24 00:22:11 +02:00
|
|
|
pub use std::error::Error;
|
2019-07-17 21:51:18 +02:00
|
|
|
pub use std::io::prelude::*;
|
|
|
|
pub use std::process::{Command, Stdio};
|
2019-07-16 12:28:55 +02:00
|
|
|
|
2019-07-17 20:56:15 +02:00
|
|
|
let commands = &*format!(
|
|
|
|
"
|
2019-07-16 12:28:55 +02:00
|
|
|
cd {}
|
|
|
|
{}
|
2019-07-17 20:56:15 +02:00
|
|
|
exit",
|
|
|
|
$cwd, $commands
|
|
|
|
);
|
2019-07-16 12:28:55 +02:00
|
|
|
|
2019-08-06 07:34:06 +02:00
|
|
|
let mut process = match Command::new(helpers::executable_path())
|
2019-07-16 12:28:55 +02:00
|
|
|
.stdin(Stdio::piped())
|
|
|
|
.stdout(Stdio::piped())
|
2019-07-17 20:56:15 +02:00
|
|
|
.spawn()
|
|
|
|
{
|
|
|
|
Ok(child) => child,
|
|
|
|
Err(why) => panic!("Can't run test {}", why.description()),
|
2019-07-16 12:28:55 +02:00
|
|
|
};
|
|
|
|
|
2019-08-06 07:34:06 +02:00
|
|
|
let stdin = process.stdin.as_mut().expect("couldn't open stdin");
|
|
|
|
stdin
|
|
|
|
.write_all(commands.as_bytes())
|
|
|
|
.expect("couldn't write to stdin");
|
2019-07-16 12:28:55 +02:00
|
|
|
|
2019-08-06 07:34:06 +02:00
|
|
|
let output = process
|
|
|
|
.wait_with_output()
|
|
|
|
.expect("couldn't read from stdout");
|
2019-07-16 12:28:55 +02:00
|
|
|
|
2019-08-06 07:34:06 +02:00
|
|
|
let $out = String::from_utf8_lossy(&output.stdout);
|
|
|
|
let $out = $out.replace("\r\n", "");
|
|
|
|
let $out = $out.replace("\n", "");
|
2019-07-16 12:28:55 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-07-17 20:56:15 +02:00
|
|
|
#[macro_export]
|
2019-07-16 12:28:55 +02:00
|
|
|
macro_rules! nu_error {
|
|
|
|
($out:ident, $cwd:expr, $commands:expr) => {
|
|
|
|
use std::io::prelude::*;
|
|
|
|
use std::process::{Command, Stdio};
|
|
|
|
|
2019-07-17 20:56:15 +02:00
|
|
|
let commands = &*format!(
|
|
|
|
"
|
2019-07-16 12:28:55 +02:00
|
|
|
cd {}
|
|
|
|
{}
|
2019-07-17 20:56:15 +02:00
|
|
|
exit",
|
|
|
|
$cwd, $commands
|
|
|
|
);
|
2019-07-16 12:28:55 +02:00
|
|
|
|
|
|
|
let mut process = Command::new(helpers::executable_path())
|
|
|
|
.stdin(Stdio::piped())
|
|
|
|
.stderr(Stdio::piped())
|
|
|
|
.spawn()
|
|
|
|
.expect("couldn't run test");
|
|
|
|
|
|
|
|
let stdin = process.stdin.as_mut().expect("couldn't open stdin");
|
2019-07-17 20:56:15 +02:00
|
|
|
stdin
|
|
|
|
.write_all(commands.as_bytes())
|
|
|
|
.expect("couldn't write to stdin");
|
2019-07-16 12:28:55 +02:00
|
|
|
|
2019-07-17 20:56:15 +02:00
|
|
|
let output = process
|
|
|
|
.wait_with_output()
|
|
|
|
.expect("couldn't read from stderr");
|
2019-07-16 12:28:55 +02:00
|
|
|
let $out = String::from_utf8_lossy(&output.stderr);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-08-01 23:00:08 +02:00
|
|
|
pub enum Stub<'a> {
|
|
|
|
FileWithContent(&'a str, &'a str),
|
2019-08-25 14:59:46 +02:00
|
|
|
FileWithContentToBeTrimmed(&'a str, &'a str),
|
2019-08-01 23:00:08 +02:00
|
|
|
EmptyFile(&'a str),
|
|
|
|
}
|
2019-07-24 06:10:48 +02:00
|
|
|
|
2019-08-01 23:00:08 +02:00
|
|
|
pub struct Playground {
|
|
|
|
tests: String,
|
|
|
|
cwd: PathBuf,
|
2019-07-21 09:08:05 +02:00
|
|
|
}
|
|
|
|
|
2019-08-01 23:00:08 +02:00
|
|
|
impl Playground {
|
|
|
|
pub fn root() -> String {
|
|
|
|
String::from("tests/fixtures/nuplayground")
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn test_dir_name(&self) -> String {
|
|
|
|
self.tests.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn back_to_playground(&mut self) -> &mut Self {
|
|
|
|
self.cwd = PathBuf::from([Playground::root(), self.tests.clone()].join("/"));
|
|
|
|
self
|
|
|
|
}
|
2019-08-02 21:15:07 +02:00
|
|
|
|
2019-08-01 23:00:08 +02:00
|
|
|
pub fn setup_for(topic: &str) -> Playground {
|
|
|
|
let nuplay_dir = format!("{}/{}", Playground::root(), topic);
|
|
|
|
|
|
|
|
if PathBuf::from(&nuplay_dir).exists() {
|
|
|
|
std::fs::remove_dir_all(PathBuf::from(&nuplay_dir)).expect("can not remove directory");
|
|
|
|
}
|
|
|
|
|
|
|
|
std::fs::create_dir(PathBuf::from(&nuplay_dir)).expect("can not create directory");
|
|
|
|
|
|
|
|
Playground {
|
|
|
|
tests: topic.to_string(),
|
|
|
|
cwd: PathBuf::from([Playground::root(), topic.to_string()].join("/")),
|
|
|
|
}
|
|
|
|
}
|
2019-07-21 09:08:05 +02:00
|
|
|
|
2019-08-14 22:07:08 +02:00
|
|
|
pub fn mkdir(&mut self, directory: &str) -> &mut Self {
|
|
|
|
self.cwd.push(directory);
|
|
|
|
std::fs::create_dir_all(&self.cwd).expect("can not create directory");
|
|
|
|
self.back_to_playground();
|
2019-08-01 23:00:08 +02:00
|
|
|
self
|
2019-07-21 09:08:05 +02:00
|
|
|
}
|
|
|
|
|
2019-08-01 23:00:08 +02:00
|
|
|
pub fn with_files(&mut self, files: Vec<Stub>) -> &mut Self {
|
2019-08-25 14:59:46 +02:00
|
|
|
let endl = line_ending();
|
|
|
|
|
2019-08-01 23:00:08 +02:00
|
|
|
files
|
|
|
|
.iter()
|
|
|
|
.map(|f| {
|
|
|
|
let mut path = PathBuf::from(&self.cwd);
|
|
|
|
|
|
|
|
let (file_name, contents) = match *f {
|
2019-08-25 14:59:46 +02:00
|
|
|
Stub::EmptyFile(name) => (name, "fake data".to_string()),
|
|
|
|
Stub::FileWithContent(name, content) => (name, content.to_string()),
|
|
|
|
Stub::FileWithContentToBeTrimmed(name, content) => (
|
|
|
|
name,
|
|
|
|
content
|
|
|
|
.lines()
|
|
|
|
.skip(1)
|
|
|
|
.map(|line| line.trim())
|
|
|
|
.collect::<Vec<&str>>()
|
|
|
|
.join(&endl),
|
|
|
|
),
|
2019-08-01 23:00:08 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
path.push(file_name);
|
|
|
|
|
|
|
|
std::fs::write(PathBuf::from(path), contents.as_bytes())
|
|
|
|
.expect("can not create file");
|
|
|
|
})
|
|
|
|
.for_each(drop);
|
|
|
|
self.back_to_playground();
|
|
|
|
self
|
|
|
|
}
|
2019-07-21 09:08:05 +02:00
|
|
|
|
2019-08-01 23:00:08 +02:00
|
|
|
pub fn within(&mut self, directory: &str) -> &mut Self {
|
|
|
|
self.cwd.push(directory);
|
|
|
|
std::fs::create_dir(&self.cwd).expect("can not create directory");
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn glob_vec(pattern: &str) -> Vec<PathBuf> {
|
2019-08-19 02:12:28 +02:00
|
|
|
let glob = glob(pattern);
|
|
|
|
|
|
|
|
match glob {
|
|
|
|
Ok(paths) => paths
|
|
|
|
.map(|path| {
|
|
|
|
if let Ok(path) = path {
|
|
|
|
path
|
|
|
|
} else {
|
|
|
|
unreachable!()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect(),
|
|
|
|
Err(_) => panic!("Invalid pattern."),
|
|
|
|
}
|
2019-08-01 23:00:08 +02:00
|
|
|
}
|
2019-07-21 09:08:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn file_contents(full_path: &str) -> String {
|
2019-08-01 10:31:41 +02:00
|
|
|
let mut file = std::fs::File::open(full_path).expect("can not open file");
|
2019-07-24 00:22:11 +02:00
|
|
|
let mut contents = String::new();
|
|
|
|
file.read_to_string(&mut contents)
|
|
|
|
.expect("can not read file");
|
|
|
|
contents
|
2019-07-21 09:08:05 +02:00
|
|
|
}
|
|
|
|
|
2019-08-25 14:59:46 +02:00
|
|
|
pub fn line_ending() -> String {
|
|
|
|
#[cfg(windows)]
|
|
|
|
{
|
|
|
|
String::from("\r\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
{
|
|
|
|
String::from("\n")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-02 18:33:52 +02:00
|
|
|
pub fn normalize_string(input: &str) -> String {
|
|
|
|
#[cfg(windows)]
|
|
|
|
{
|
|
|
|
input.to_string()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(windows))]
|
|
|
|
{
|
|
|
|
format!("\"{}\"", input)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-24 06:10:48 +02:00
|
|
|
pub fn create_file_at(full_path: impl AsRef<Path>) -> Result<(), std::io::Error> {
|
|
|
|
let full_path = full_path.as_ref();
|
|
|
|
|
2019-08-19 02:12:28 +02:00
|
|
|
if let Some(parent) = full_path.parent() {
|
|
|
|
panic!(format!("{:?} exists", parent.display()));
|
|
|
|
}
|
|
|
|
|
2019-07-24 06:10:48 +02:00
|
|
|
std::fs::write(full_path, "fake data".as_bytes())
|
2019-07-17 21:51:18 +02:00
|
|
|
}
|
|
|
|
|
2019-08-01 10:31:41 +02:00
|
|
|
pub fn copy_file_to(source: &str, destination: &str) {
|
|
|
|
std::fs::copy(source, destination).expect("can not copy file");
|
2019-07-17 21:51:18 +02:00
|
|
|
}
|
|
|
|
|
2019-08-06 09:05:47 +02:00
|
|
|
pub fn files_exist_at(files: Vec<&Path>, path: PathBuf) -> bool {
|
2019-08-07 04:45:38 +02:00
|
|
|
files.iter().all(|f| {
|
|
|
|
let mut loc = path.clone();
|
|
|
|
loc.push(f);
|
|
|
|
loc.exists()
|
|
|
|
})
|
2019-07-17 21:51:18 +02:00
|
|
|
}
|
|
|
|
|
2019-08-06 09:05:47 +02:00
|
|
|
pub fn file_exists_at(path: PathBuf) -> bool {
|
|
|
|
path.exists()
|
|
|
|
}
|
2019-07-24 00:22:11 +02:00
|
|
|
|
2019-08-06 09:05:47 +02:00
|
|
|
pub fn dir_exists_at(path: PathBuf) -> bool {
|
|
|
|
path.exists()
|
2019-08-06 07:34:06 +02:00
|
|
|
}
|
2019-07-24 00:22:11 +02:00
|
|
|
|
2019-07-17 21:51:18 +02:00
|
|
|
pub fn delete_directory_at(full_path: &str) {
|
|
|
|
std::fs::remove_dir_all(PathBuf::from(full_path)).expect("can not remove directory");
|
|
|
|
}
|
|
|
|
|
2019-07-16 12:28:55 +02:00
|
|
|
pub fn executable_path() -> PathBuf {
|
|
|
|
let mut buf = PathBuf::new();
|
2019-07-17 20:56:15 +02:00
|
|
|
buf.push("target");
|
|
|
|
buf.push("debug");
|
|
|
|
buf.push("nu");
|
|
|
|
buf
|
2019-07-16 12:28:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn in_directory(str: &str) -> &str {
|
|
|
|
str
|
2019-07-16 12:53:19 +02:00
|
|
|
}
|