From 5bce22093b4b0778f729d8d92e37f42214f78fc5 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Mon, 10 Jan 2022 23:01:56 -0500 Subject: add tests --- src/parse.rs | 10 ++-- src/parse/test_ast.rs | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++ 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, } @@ -11,7 +11,7 @@ impl Pipeline { } } -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub struct Exe { exe: std::path::PathBuf, args: Vec, @@ -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, 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 + = 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); +} -- cgit v1.2.3-54-g00ecf