summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-01-10 23:01:56 -0500
committerJesse Luehrs <doy@tozt.net>2022-01-10 23:01:56 -0500
commit5bce22093b4b0778f729d8d92e37f42214f78fc5 (patch)
tree67273fffaa237d9a6c6d0b8cd2e9c1987345ea94
parent3c18ba5b58f4239054e809b07d795308f75b8602 (diff)
downloadnbsh-5bce22093b4b0778f729d8d92e37f42214f78fc5.tar.gz
nbsh-5bce22093b4b0778f729d8d92e37f42214f78fc5.zip
add tests
-rw-r--r--src/parse.rs10
-rw-r--r--src/parse/test_ast.rs123
2 files changed, 128 insertions, 5 deletions
diff --git a/src/parse.rs b/src/parse.rs
index 09cdb91..cc6d92b 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -1,6 +1,6 @@
pub mod ast;
-#[derive(Debug)]
+#[derive(Debug, Eq, PartialEq)]
pub struct Pipeline {
exes: Vec<Exe>,
}
@@ -11,7 +11,7 @@ impl Pipeline {
}
}
-#[derive(Debug)]
+#[derive(Debug, Eq, PartialEq)]
pub struct Exe {
exe: std::path::PathBuf,
args: Vec<String>,
@@ -36,14 +36,14 @@ impl Exe {
}
}
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Redirect {
pub from: std::os::unix::io::RawFd,
pub to: RedirectTarget,
pub dir: Direction,
}
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Eq, PartialEq)]
pub enum RedirectTarget {
Fd(std::os::unix::io::RawFd),
File(std::path::PathBuf),
@@ -99,7 +99,7 @@ impl Direction {
}
}
-#[derive(Debug)]
+#[derive(Debug, Eq, PartialEq)]
pub struct Error {
input: String,
e: pest::error::Error<ast::Rule>,
diff --git a/src/parse/test_ast.rs b/src/parse/test_ast.rs
index 19bf7af..e295afd 100644
--- a/src/parse/test_ast.rs
+++ b/src/parse/test_ast.rs
@@ -25,6 +25,14 @@ macro_rules! p {
};
}
+macro_rules! ep {
+ ($($exes:expr),*) => {
+ super::super::Pipeline {
+ exes: vec![$($exes),*],
+ }
+ };
+}
+
macro_rules! e {
($word:expr) => {
Exe {
@@ -56,6 +64,26 @@ macro_rules! e {
};
}
+macro_rules! ee {
+ ($exe:expr) => {
+ super::super::Exe {
+ exe: std::path::PathBuf::from($exe.to_string()),
+ args: vec![],
+ redirects: vec![],
+ }
+ };
+ ($exe:expr, $($args:expr),*) => {
+ super::super::Exe {
+ exe: std::path::PathBuf::from($exe.to_string()),
+ args: [$($args),*]
+ .into_iter()
+ .map(|s| s.to_string())
+ .collect(),
+ redirects: vec![],
+ }
+ };
+}
+
macro_rules! r {
($from:literal, $to:expr, $dir:ident) => {
Redirect {
@@ -115,6 +143,42 @@ macro_rules! parse_eq {
};
}
+macro_rules! eval_eq {
+ ($line:literal, $env:expr, $($evaled:expr),*) => {{
+ let ast = Commands::parse($line).unwrap();
+ let mut expected: Vec<super::super::Pipeline>
+ = vec![$($evaled),*];
+ for command in ast.commands {
+ let pipeline = match command {
+ Command::Pipeline(p)
+ | Command::If(p)
+ | Command::While(p) => p,
+ _ => continue,
+ };
+ assert_eq!(pipeline.eval(&$env).unwrap(), expected.remove(0));
+ }
+ }};
+}
+
+macro_rules! eval_fails {
+ ($line:literal, $env:expr) => {{
+ let ast = Commands::parse($line).unwrap();
+ let mut fail = false;
+ for command in ast.commands {
+ let pipeline = match command {
+ Command::Pipeline(p) | Command::If(p) | Command::While(p) => {
+ p
+ }
+ _ => continue,
+ };
+ if pipeline.eval(&$env).is_err() {
+ fail = true;
+ }
+ }
+ assert!(fail)
+ }};
+}
+
#[test]
fn test_basic() {
parse_eq!("foo", cs!(p!(e!(w!("foo")))));
@@ -287,3 +351,62 @@ fn test_alternation() {
)))
);
}
+
+#[test]
+fn test_eval_alternation() {
+ let mut env = Env::new();
+ env.set_var("HOME", "/home/test");
+ env.set_var("foo", "value-of-foo");
+
+ eval_eq!("echo {foo,bar}", env, ep!(ee!("echo", "foo", "bar")));
+ eval_eq!(
+ "echo {foo,bar}.rs",
+ env,
+ ep!(ee!("echo", "foo.rs", "bar.rs"))
+ );
+ eval_eq!(
+ "echo {foo,bar,baz}.rs",
+ env,
+ ep!(ee!("echo", "foo.rs", "bar.rs", "baz.rs"))
+ );
+ eval_eq!("echo {foo,}.rs", env, ep!(ee!("echo", "foo.rs", ".rs")));
+ eval_eq!("echo {foo}", env, ep!(ee!("echo", "foo")));
+ eval_eq!("echo {}", env, ep!(ee!("echo", "")));
+ eval_eq!(
+ "echo {foo,bar}.{rs,c}",
+ env,
+ ep!(ee!("echo", "foo.rs", "foo.c", "bar.rs", "bar.c"))
+ );
+ eval_eq!(
+ "echo {$foo,\"${HOME}/bin\"}.{'r'\"s\",c}",
+ env,
+ ep!(ee!(
+ "echo",
+ "value-of-foo.rs",
+ "value-of-foo.c",
+ "/home/test/bin.rs",
+ "/home/test/bin.c"
+ ))
+ );
+}
+
+#[test]
+fn test_eval_glob() {
+ let env = Env::new();
+
+ eval_eq!(
+ "echo *.toml",
+ env,
+ ep!(ee!("echo", "Cargo.toml", "deny.toml"))
+ );
+ eval_eq!("echo .*.toml", env, ep!(ee!("echo", ".rustfmt.toml")));
+ eval_eq!(
+ "echo *.{lock,toml}",
+ env,
+ ep!(ee!("echo", "Cargo.lock", "Cargo.toml", "deny.toml"))
+ );
+ eval_eq!("echo foo]", env, ep!(ee!("echo", "foo]")));
+ eval_fails!("echo foo[", env);
+ eval_fails!("echo *.doesnotexist", env);
+ eval_fails!("echo *.{toml,doesnotexist}", env);
+}