From 6c958c34efeacb84a4802a290bd6b568cdd99a12 Mon Sep 17 00:00:00 2001
From: prsabahrami
Date: Tue, 10 Sep 2024 10:33:14 -0400
Subject: [PATCH 1/6] Added tests on parser.rs
---
crates/deno_task_shell/src/grammar.pest | 2 -
crates/deno_task_shell/src/parser.rs | 368 +++++++++++++++++++++++-
2 files changed, 367 insertions(+), 3 deletions(-)
diff --git a/crates/deno_task_shell/src/grammar.pest b/crates/deno_task_shell/src/grammar.pest
index 8909557..c104886 100644
--- a/crates/deno_task_shell/src/grammar.pest
+++ b/crates/deno_task_shell/src/grammar.pest
@@ -85,8 +85,6 @@ DLESSDASH = { "<<-" }
CLOBBER = { ">|" }
AMPERSAND = { "&" }
EXIT_STATUS = ${ "$?" }
-TILDE = ${ "~" }
-
// Operators
OPERATOR = _{
diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs
index 414b66a..07d8916 100644
--- a/crates/deno_task_shell/src/parser.rs
+++ b/crates/deno_task_shell/src/parser.rs
@@ -517,7 +517,7 @@ fn parse_shell_var(pair: Pair) -> Result {
let value = inner
.next()
.ok_or_else(|| anyhow::anyhow!("Expected variable value"))?;
- let value = parse_word(value)?;
+ let value = parse_assignment_value(value)?;
Ok(Sequence::ShellVar(EnvVar { name, value }))
}
@@ -1046,7 +1046,373 @@ mod test {
assert!(parse("echo \"foo\" > out.txt").is_ok());
}
+ #[test]
+ fn test_sequential_list() {
+ let parse_and_create = |input: &str| -> Result {
+ let pairs = ShellParser::parse(Rule::complete_command, input)
+ .map_err(|e| anyhow::Error::msg(e.to_string()))?
+ .next()
+ .unwrap();
+ // println!("pairs: {:?}", pairs);
+ parse_complete_command(pairs)
+ };
+
+ // Test case 1
+ let input = concat!(
+ "Name=Value OtherVar=Other command arg1 || command2 arg12 arg13 ; ",
+ "command3 && command4 & command5 ; export ENV6=5 ; ",
+ "ENV7=other && command8 || command9 ; ",
+ "cmd10 && (cmd11 || cmd12)"
+ );
+ let result = parse_and_create(input).unwrap();
+ let expected = SequentialList {
+ items: vec![
+ SequentialListItem {
+ is_async: false,
+ sequence: Sequence::BooleanList(Box::new(BooleanList {
+ current: SimpleCommand {
+ env_vars: vec![
+ EnvVar::new("Name".to_string(), Word::new_word("Value")),
+ EnvVar::new("OtherVar".to_string(), Word::new_word("Other")),
+ ],
+ args: vec![Word::new_word("command"), Word::new_word("arg1")],
+ }
+ .into(),
+ op: BooleanListOperator::Or,
+ next: SimpleCommand {
+ env_vars: vec![],
+ args: vec![
+ Word::new_word("command2"),
+ Word::new_word("arg12"),
+ Word::new_word("arg13"),
+ ],
+ }
+ .into(),
+ })),
+ },
+ SequentialListItem {
+ is_async: true,
+ sequence: Sequence::BooleanList(Box::new(BooleanList {
+ current: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("command3")],
+ }
+ .into(),
+ op: BooleanListOperator::And,
+ next: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("command4")],
+ }
+ .into(),
+ })),
+ },
+ SequentialListItem {
+ is_async: false,
+ sequence: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("command5")],
+ }
+ .into(),
+ },
+ SequentialListItem {
+ is_async: false,
+ sequence: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("export"), Word::new_word("ENV6=5")],
+ }
+ .into(),
+ },
+ SequentialListItem {
+ is_async: false,
+ sequence: Sequence::BooleanList(Box::new(BooleanList {
+ current: Sequence::ShellVar(EnvVar::new(
+ "ENV7".to_string(),
+ Word::new_word("other"),
+ )),
+ op: BooleanListOperator::And,
+ next: Sequence::BooleanList(Box::new(BooleanList {
+ current: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("command8")],
+ }
+ .into(),
+ op: BooleanListOperator::Or,
+ next: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("command9")],
+ }
+ .into(),
+ })),
+ })),
+ },
+ SequentialListItem {
+ is_async: false,
+ sequence: Sequence::BooleanList(Box::new(BooleanList {
+ current: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("cmd10")],
+ }
+ .into(),
+ op: BooleanListOperator::And,
+ next: Command {
+ inner: CommandInner::Subshell(Box::new(SequentialList {
+ items: vec![SequentialListItem {
+ is_async: false,
+ sequence: Sequence::BooleanList(Box::new(BooleanList {
+ current: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("cmd11")],
+ }
+ .into(),
+ op: BooleanListOperator::Or,
+ next: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("cmd12")],
+ }
+ .into(),
+ })),
+ }],
+ })),
+ redirect: None,
+ }
+ .into(),
+ })),
+ },
+ ],
+ };
+ assert_eq!(result, expected);
+
+ // Test case 2
+ let input = "command1 ; command2 ; A='b' command3";
+ let result = parse_and_create(input).unwrap();
+ let expected = SequentialList {
+ items: vec![
+ SequentialListItem {
+ is_async: false,
+ sequence: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("command1")],
+ }
+ .into(),
+ },
+ SequentialListItem {
+ is_async: false,
+ sequence: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("command2")],
+ }
+ .into(),
+ },
+ SequentialListItem {
+ is_async: false,
+ sequence: SimpleCommand {
+ env_vars: vec![EnvVar::new("A".to_string(), Word::new_string("b"))],
+ args: vec![Word::new_word("command3")],
+ }
+ .into(),
+ },
+ ],
+ };
+ assert_eq!(result, expected);
+
+ // Test case 3
+ let input = "test &&";
+ assert!(parse_and_create(input).is_err());
+
+ // Test case 4
+ let input = "command &";
+ let result = parse_and_create(input).unwrap();
+ let expected = SequentialList {
+ items: vec![SequentialListItem {
+ is_async: true,
+ sequence: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("command")],
+ }
+ .into(),
+ }],
+ };
+ assert_eq!(result, expected);
+
+ // Test case 5
+ let input = "test | other";
+ let result = parse_and_create(input).unwrap();
+ let expected = SequentialList {
+ items: vec![SequentialListItem {
+ is_async: false,
+ sequence: PipeSequence {
+ current: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("test")],
+ }
+ .into(),
+ op: PipeSequenceOperator::Stdout,
+ next: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("other")],
+ }
+ .into(),
+ }
+ .into(),
+ }],
+ };
+ assert_eq!(result, expected);
+
+ // Test case 6
+ let input = "test |& other";
+ let result = parse_and_create(input).unwrap();
+ let expected = SequentialList {
+ items: vec![SequentialListItem {
+ is_async: false,
+ sequence: PipeSequence {
+ current: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("test")],
+ }
+ .into(),
+ op: PipeSequenceOperator::StdoutStderr,
+ next: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("other")],
+ }
+ .into(),
+ }
+ .into(),
+ }],
+ };
+ assert_eq!(result, expected);
+
+ // Test case 8
+ let input = "echo $MY_ENV;";
+ let result = parse_and_create(input).unwrap();
+ let expected = SequentialList {
+ items: vec![SequentialListItem {
+ is_async: false,
+ sequence: SimpleCommand {
+ env_vars: vec![],
+ args: vec![
+ Word::new_word("echo"),
+ Word(vec![WordPart::Variable("MY_ENV".to_string())]),
+ ],
+ }
+ .into(),
+ }],
+ };
+ assert_eq!(result, expected);
+
+ // Test case 9
+ let input = "! cmd1 | cmd2 && cmd3";
+ let result = parse_and_create(input).unwrap();
+ let expected = SequentialList {
+ items: vec![SequentialListItem {
+ is_async: false,
+ sequence: Sequence::BooleanList(Box::new(BooleanList {
+ current: Pipeline {
+ negated: true,
+ inner: PipeSequence {
+ current: SimpleCommand {
+ args: vec![Word::new_word("cmd1")],
+ env_vars: vec![],
+ }
+ .into(),
+ op: PipeSequenceOperator::Stdout,
+ next: SimpleCommand {
+ args: vec![Word::new_word("cmd2")],
+ env_vars: vec![],
+ }
+ .into(),
+ }
+ .into(),
+ }
+ .into(),
+ op: BooleanListOperator::And,
+ next: SimpleCommand {
+ args: vec![Word::new_word("cmd3")],
+ env_vars: vec![],
+ }
+ .into(),
+ })),
+ }],
+ };
+ assert_eq!(result, expected);
+ }
+ #[test]
+ fn test_env_var() {
+ let parse_and_create = |input: &str| -> Result {
+ let pairs = ShellParser::parse(Rule::ASSIGNMENT_WORD, input)
+ .map_err(|e| anyhow::anyhow!(e.to_string()))?
+ .next()
+ .unwrap();
+ parse_env_var(pairs)
+ };
+
+ assert_eq!(
+ parse_and_create("Name=Value").unwrap(),
+ EnvVar {
+ name: "Name".to_string(),
+ value: Word::new_word("Value"),
+ }
+ );
+
+ assert_eq!(
+ parse_and_create("Name='quoted value'").unwrap(),
+ EnvVar {
+ name: "Name".to_string(),
+ value: Word::new_string("quoted value"),
+ }
+ );
+
+ assert_eq!(
+ parse_and_create("Name=\"double quoted value\"").unwrap(),
+ EnvVar {
+ name: "Name".to_string(),
+ value: Word::new_string("double quoted value"),
+ }
+ );
+
+ assert_eq!(
+ parse_and_create("Name=").unwrap(),
+ EnvVar {
+ name: "Name".to_string(),
+ value: Word(vec![]),
+ }
+ );
+
+ assert_eq!(
+ parse_and_create("Name=$(test)").unwrap(),
+ EnvVar {
+ name: "Name".to_string(),
+ value: Word(vec![WordPart::Command(SequentialList {
+ items: vec![SequentialListItem {
+ is_async: false,
+ sequence: SimpleCommand {
+ env_vars: vec![],
+ args: vec![Word::new_word("test")],
+ }
+ .into(),
+ }],
+ })]),
+ }
+ );
+
+ assert_eq!(
+ parse_and_create("Name=$(OTHER=5)").unwrap(),
+ EnvVar {
+ name: "Name".to_string(),
+ value: Word(vec![WordPart::Command(SequentialList {
+ items: vec![SequentialListItem {
+ is_async: false,
+ sequence: Sequence::ShellVar(EnvVar {
+ name: "OTHER".to_string(),
+ value: Word::new_word("5"),
+ }),
+ }],
+ })]),
+ }
+ );
+ }
+
#[cfg(feature = "serialization")]
#[test]
fn serializes_command_to_json() {
From 80867d2fd9b6c6b020fbd93209e8f23edc52d06a Mon Sep 17 00:00:00 2001
From: prsabahrami
Date: Tue, 10 Sep 2024 10:58:16 -0400
Subject: [PATCH 2/6] Added tests on shell
---
crates/deno_task_shell/src/grammar.pest | 2 +-
crates/deno_task_shell/src/shell/test.rs | 113 ++++++++++++++++++
.../deno_task_shell/src/shell/test_builder.rs | 31 ++++-
3 files changed, 144 insertions(+), 2 deletions(-)
diff --git a/crates/deno_task_shell/src/grammar.pest b/crates/deno_task_shell/src/grammar.pest
index c104886..f9ed255 100644
--- a/crates/deno_task_shell/src/grammar.pest
+++ b/crates/deno_task_shell/src/grammar.pest
@@ -62,7 +62,7 @@ DOUBLE_QUOTED = @{ "\"" ~ QUOTED_PENDING_WORD ~ "\"" }
SINGLE_QUOTED = @{ "'" ~ (!"'" ~ ANY)* ~ "'" }
NAME = ${ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }
-ASSIGNMENT_WORD = { NAME ~ "=" ~ ASSIGNMENT_VALUE? }
+ASSIGNMENT_WORD = ${ NAME ~ "=" ~ ASSIGNMENT_VALUE? }
ASSIGNMENT_VALUE = ${
ASSIGNMENT_TILDE_PREFIX ~
((":" ~ ASSIGNMENT_TILDE_PREFIX) | (!":" ~ UNQUOTED_PENDING_WORD))* |
diff --git a/crates/deno_task_shell/src/shell/test.rs b/crates/deno_task_shell/src/shell/test.rs
index 43293d4..226e7b6 100644
--- a/crates/deno_task_shell/src/shell/test.rs
+++ b/crates/deno_task_shell/src/shell/test.rs
@@ -7,6 +7,119 @@ use super::types::ExecuteResult;
const FOLDER_SEPARATOR: char = if cfg!(windows) { '\\' } else { '/' };
+#[tokio::test]
+async fn commands() {
+ TestBuilder::new()
+ .command("echo 1")
+ .assert_stdout("1\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command("echo 1 2 3")
+ .assert_stdout("1 2 3\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(r#"echo "1 2 3""#)
+ .assert_stdout("1 2 3\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(r"echo 1 2\ \ \ 3")
+ .assert_stdout("1 2 3\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(r#"echo "1 2\ \ \ 3""#)
+ .assert_stdout("1 2\\ \\ \\ 3\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(r#"echo test$(echo "1 2")"#)
+ .assert_stdout("test1 2\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(r#"TEST="1 2" ; echo $TEST"#)
+ .assert_stdout("1 2\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(
+ r#"VAR=1 deno eval 'console.log(Deno.env.get("VAR"))' && echo $VAR"#,
+ )
+ .assert_stdout("1\n\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(r#"VAR=1 VAR2=2 deno eval 'console.log(Deno.env.get("VAR") + Deno.env.get("VAR2"))'"#)
+ .assert_stdout("12\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(
+ r#"EMPTY= deno eval 'console.log(`EMPTY: ${Deno.env.get("EMPTY")}`)'"#,
+ )
+ .assert_stdout("EMPTY: \n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(r#""echo" "1""#)
+ .assert_stdout("1\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(r#""echo" "*""#)
+ .assert_stdout("*\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command("echo test-dashes")
+ .assert_stdout("test-dashes\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command("echo 'a/b'/c")
+ .assert_stdout("a/b/c\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command("echo 'a/b'ctest\"te st\"'asdf'")
+ .assert_stdout("a/bctestte stasdf\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command("echo --test=\"2\" --test='2' test\"TEST\" TEST'test'TEST 'test''test' test'test'\"test\" \"test\"\"test\"'test'")
+ .assert_stdout("--test=2 --test=2 testTEST TESTtestTEST testtest testtesttest testtesttest\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command("deno eval 'console.log(1)'")
+ .env_var("PATH", "")
+ .assert_stderr("deno: command not found\n")
+ .assert_exit_code(127)
+ .run()
+ .await;
+
+ TestBuilder::new().command("unset").run().await;
+}
+
#[tokio::test]
async fn boolean_logic() {
TestBuilder::new()
diff --git a/crates/deno_task_shell/src/shell/test_builder.rs b/crates/deno_task_shell/src/shell/test_builder.rs
index e3acb33..9dece43 100644
--- a/crates/deno_task_shell/src/shell/test_builder.rs
+++ b/crates/deno_task_shell/src/shell/test_builder.rs
@@ -1,5 +1,5 @@
// Copyright 2018-2024 the Deno authors. MIT license.
-
+use anyhow::Context;
use futures::future::LocalBoxFuture;
use pretty_assertions::assert_eq;
use std::collections::HashMap;
@@ -39,6 +39,7 @@ impl ShellCommand for FnShellCommand {
enum TestAssertion {
FileExists(String),
FileNotExists(String),
+ FileTextEquals(String, String),
}
struct TempDir {
@@ -132,6 +133,11 @@ impl TestBuilder {
self
}
+ pub fn env_var(&mut self, name: &str, value: &str) -> &mut Self {
+ self.env_vars.insert(name.to_string(), value.to_string());
+ self
+ }
+
pub fn custom_command(
&mut self,
name: &str,
@@ -143,6 +149,19 @@ impl TestBuilder {
self
}
+ pub fn assert_file_equals(
+ &mut self,
+ path: &str,
+ file_text: &str,
+ ) -> &mut Self {
+ self.ensure_temp_dir();
+ self.assertions.push(TestAssertion::FileTextEquals(
+ path.to_string(),
+ file_text.to_string(),
+ ));
+ self
+ }
+
pub fn file(&mut self, path: &str, text: &str) -> &mut Self {
let temp_dir = self.get_temp_dir();
fs::write(temp_dir.cwd.join(path), text).unwrap();
@@ -243,6 +262,16 @@ impl TestBuilder {
path,
)
}
+ TestAssertion::FileTextEquals(path, text) => {
+ let actual_text = std::fs::read_to_string(cwd.join(path))
+ .with_context(|| format!("Error reading {path}"))
+ .unwrap();
+ assert_eq!(
+ &actual_text, text,
+ "\n\nFailed for: {}\nPath: {}",
+ self.command, path,
+ )
+ }
}
}
}
From 705a95d9d925448f58110fef7695de49649c54c1 Mon Sep 17 00:00:00 2001
From: prsabahrami
Date: Tue, 10 Sep 2024 11:00:19 -0400
Subject: [PATCH 3/6] run fmt
---
crates/deno_task_shell/src/parser.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crates/deno_task_shell/src/parser.rs b/crates/deno_task_shell/src/parser.rs
index 07d8916..87c778f 100644
--- a/crates/deno_task_shell/src/parser.rs
+++ b/crates/deno_task_shell/src/parser.rs
@@ -1412,7 +1412,7 @@ mod test {
}
);
}
-
+
#[cfg(feature = "serialization")]
#[test]
fn serializes_command_to_json() {
From 851099573bf16d3f6291fb3c923e85f2702e4e0e Mon Sep 17 00:00:00 2001
From: prsabahrami
Date: Tue, 10 Sep 2024 14:20:32 -0400
Subject: [PATCH 4/6] Fixes
---
crates/deno_task_shell/src/shell/test.rs | 70 +++++++++++++++++++
.../deno_task_shell/src/shell/test_builder.rs | 26 +++----
2 files changed, 83 insertions(+), 13 deletions(-)
diff --git a/crates/deno_task_shell/src/shell/test.rs b/crates/deno_task_shell/src/shell/test.rs
index 226e7b6..90eae50 100644
--- a/crates/deno_task_shell/src/shell/test.rs
+++ b/crates/deno_task_shell/src/shell/test.rs
@@ -236,6 +236,76 @@ async fn sequential_lists() {
.run()
.await;
}
+#[tokio::test]
+async fn pipeline() {
+ TestBuilder::new()
+ .command(r#"echo 1 | deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)'"#)
+ .assert_stdout("1\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(r#"echo 1 | echo 2 && echo 3"#)
+ .assert_stdout("2\n3\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(r#"echo $(sleep 0.1 && echo 2 & echo 1) | deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)'"#)
+ .assert_stdout("1 2\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(r#"echo 2 | echo 1 | deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)'"#)
+ .assert_stdout("1\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ .command(r#"deno eval 'console.log(1); console.error(2);' | deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)'"#)
+ .assert_stdout("1\n")
+ .assert_stderr("2\n")
+ .run()
+ .await;
+
+ // stdout and stderr pipeline
+
+ TestBuilder::new()
+ .command(r#"deno eval 'console.log(1); console.error(2);' |& deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)'"#)
+ .assert_stdout("1\n2\n")
+ .run()
+ .await;
+
+ TestBuilder::new()
+ // add bit of a delay while outputting stdout so that it doesn't race with stderr
+ .command(r#"deno eval 'console.log(1); console.error(2);' | deno eval 'setTimeout(async () => { await Deno.stdin.readable.pipeTo(Deno.stderr.writable) }, 10)' |& deno eval 'await Deno.stdin.readable.pipeTo(Deno.stderr.writable)'"#)
+ // still outputs 2 because the first command didn't pipe stderr
+ .assert_stderr("2\n1\n")
+ .run()
+ .await;
+
+ // |& pipeline should still pipe stdout
+ TestBuilder::new()
+ .command(r#"echo 1 |& deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)'"#)
+ .assert_stdout("1\n")
+ .run()
+ .await;
+
+ // pipeline with redirect
+ TestBuilder::new()
+ .command(r#"echo 1 | deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)' > output.txt"#)
+ .assert_file_equals("output.txt", "1\n")
+ .run()
+ .await;
+
+ // pipeline with stderr redirect
+ TestBuilder::new()
+ .command(r#"echo 1 | deno eval 'await Deno.stdin.readable.pipeTo(Deno.stderr.writable)' 2> output.txt"#)
+ .assert_file_equals("output.txt", "1\n")
+ .run()
+ .await;
+}
#[tokio::test]
async fn redirects_input() {
diff --git a/crates/deno_task_shell/src/shell/test_builder.rs b/crates/deno_task_shell/src/shell/test_builder.rs
index 9dece43..387cc26 100644
--- a/crates/deno_task_shell/src/shell/test_builder.rs
+++ b/crates/deno_task_shell/src/shell/test_builder.rs
@@ -149,19 +149,6 @@ impl TestBuilder {
self
}
- pub fn assert_file_equals(
- &mut self,
- path: &str,
- file_text: &str,
- ) -> &mut Self {
- self.ensure_temp_dir();
- self.assertions.push(TestAssertion::FileTextEquals(
- path.to_string(),
- file_text.to_string(),
- ));
- self
- }
-
pub fn file(&mut self, path: &str, text: &str) -> &mut Self {
let temp_dir = self.get_temp_dir();
fs::write(temp_dir.cwd.join(path), text).unwrap();
@@ -199,6 +186,19 @@ impl TestBuilder {
self
}
+ pub fn assert_file_equals(
+ &mut self,
+ path: &str,
+ file_text: &str,
+ ) -> &mut Self {
+ self.ensure_temp_dir();
+ self.assertions.push(TestAssertion::FileTextEquals(
+ path.to_string(),
+ file_text.to_string(),
+ ));
+ self
+ }
+
pub async fn run(&mut self) {
let list = parse(&self.command).unwrap();
let cwd = if let Some(temp_dir) = &self.temp_dir {
From 4a42c8501fe713e009566b5d2894a3937d0dc2a6 Mon Sep 17 00:00:00 2001
From: prsabahrami
Date: Tue, 10 Sep 2024 17:49:52 -0400
Subject: [PATCH 5/6] Remove deno files
---
crates/deno_task_shell/src/shell/test.rs | 100 +----------------------
1 file changed, 1 insertion(+), 99 deletions(-)
diff --git a/crates/deno_task_shell/src/shell/test.rs b/crates/deno_task_shell/src/shell/test.rs
index 90eae50..c8605f3 100644
--- a/crates/deno_task_shell/src/shell/test.rs
+++ b/crates/deno_task_shell/src/shell/test.rs
@@ -51,28 +51,6 @@ async fn commands() {
.run()
.await;
- TestBuilder::new()
- .command(
- r#"VAR=1 deno eval 'console.log(Deno.env.get("VAR"))' && echo $VAR"#,
- )
- .assert_stdout("1\n\n")
- .run()
- .await;
-
- TestBuilder::new()
- .command(r#"VAR=1 VAR2=2 deno eval 'console.log(Deno.env.get("VAR") + Deno.env.get("VAR2"))'"#)
- .assert_stdout("12\n")
- .run()
- .await;
-
- TestBuilder::new()
- .command(
- r#"EMPTY= deno eval 'console.log(`EMPTY: ${Deno.env.get("EMPTY")}`)'"#,
- )
- .assert_stdout("EMPTY: \n")
- .run()
- .await;
-
TestBuilder::new()
.command(r#""echo" "1""#)
.assert_stdout("1\n")
@@ -109,14 +87,6 @@ async fn commands() {
.run()
.await;
- TestBuilder::new()
- .command("deno eval 'console.log(1)'")
- .env_var("PATH", "")
- .assert_stderr("deno: command not found\n")
- .assert_exit_code(127)
- .run()
- .await;
-
TestBuilder::new().command("unset").run().await;
}
@@ -238,12 +208,6 @@ async fn sequential_lists() {
}
#[tokio::test]
async fn pipeline() {
- TestBuilder::new()
- .command(r#"echo 1 | deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)'"#)
- .assert_stdout("1\n")
- .run()
- .await;
-
TestBuilder::new()
.command(r#"echo 1 | echo 2 && echo 3"#)
.assert_stdout("2\n3\n")
@@ -251,57 +215,8 @@ async fn pipeline() {
.await;
TestBuilder::new()
- .command(r#"echo $(sleep 0.1 && echo 2 & echo 1) | deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)'"#)
- .assert_stdout("1 2\n")
- .run()
- .await;
-
- TestBuilder::new()
- .command(r#"echo 2 | echo 1 | deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)'"#)
- .assert_stdout("1\n")
- .run()
- .await;
-
- TestBuilder::new()
- .command(r#"deno eval 'console.log(1); console.error(2);' | deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)'"#)
+ .command(r#"echo 1 | tee output.txt"#)
.assert_stdout("1\n")
- .assert_stderr("2\n")
- .run()
- .await;
-
- // stdout and stderr pipeline
-
- TestBuilder::new()
- .command(r#"deno eval 'console.log(1); console.error(2);' |& deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)'"#)
- .assert_stdout("1\n2\n")
- .run()
- .await;
-
- TestBuilder::new()
- // add bit of a delay while outputting stdout so that it doesn't race with stderr
- .command(r#"deno eval 'console.log(1); console.error(2);' | deno eval 'setTimeout(async () => { await Deno.stdin.readable.pipeTo(Deno.stderr.writable) }, 10)' |& deno eval 'await Deno.stdin.readable.pipeTo(Deno.stderr.writable)'"#)
- // still outputs 2 because the first command didn't pipe stderr
- .assert_stderr("2\n1\n")
- .run()
- .await;
-
- // |& pipeline should still pipe stdout
- TestBuilder::new()
- .command(r#"echo 1 |& deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)'"#)
- .assert_stdout("1\n")
- .run()
- .await;
-
- // pipeline with redirect
- TestBuilder::new()
- .command(r#"echo 1 | deno eval 'await Deno.stdin.readable.pipeTo(Deno.stdout.writable)' > output.txt"#)
- .assert_file_equals("output.txt", "1\n")
- .run()
- .await;
-
- // pipeline with stderr redirect
- TestBuilder::new()
- .command(r#"echo 1 | deno eval 'await Deno.stdin.readable.pipeTo(Deno.stderr.writable)' 2> output.txt"#)
.assert_file_equals("output.txt", "1\n")
.run()
.await;
@@ -678,19 +593,6 @@ async fn rm() {
#[tokio::test]
async fn windows_resolve_command() {
// not cross platform, but still allow this
- TestBuilder::new()
- .command("deno.exe eval 'console.log(1)'")
- .assert_stdout("1\n")
- .run()
- .await;
-
- TestBuilder::new()
- .command("deno eval 'console.log(1)'")
- // handle trailing semi-colon
- .env_var("PATHEXT", ".EXE;")
- .assert_stdout("1\n")
- .run()
- .await;
}
#[tokio::test]
From 8ec5549bf72ad0b1ba6dd528fb25f0c9f4eb1943 Mon Sep 17 00:00:00 2001
From: prsabahrami
Date: Tue, 10 Sep 2024 17:53:27 -0400
Subject: [PATCH 6/6] Added test for env_var
---
crates/deno_task_shell/src/shell/test.rs | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/crates/deno_task_shell/src/shell/test.rs b/crates/deno_task_shell/src/shell/test.rs
index c8605f3..1e639ed 100644
--- a/crates/deno_task_shell/src/shell/test.rs
+++ b/crates/deno_task_shell/src/shell/test.rs
@@ -87,6 +87,14 @@ async fn commands() {
.run()
.await;
+ TestBuilder::new()
+ .command("deno eval 'console.log(1)'")
+ .env_var("PATH", "")
+ .assert_stderr("deno: command not found\n")
+ .assert_exit_code(127)
+ .run()
+ .await;
+
TestBuilder::new().command("unset").run().await;
}