summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoão Souto <joao.jpgs@hotmail.com>2020-02-24 22:49:40 +0000
committerGitHub <noreply@github.com>2020-02-24 17:49:40 -0500
commitac933dd1b89a20b2e63b5d6edc5b3d0c549335bc (patch)
tree458a291c5552898728039ac855d9e4272d75ce26
parent4005174f6c584fd5200dbe450b269a7f0de487ce (diff)
port tools/repl_test.py to Rust (#4096)
ref #2988
-rw-r--r--cli/tests/integration_tests.rs196
-rw-r--r--tools/repl_test.py187
2 files changed, 193 insertions, 190 deletions
diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs
index 5429170c7..1767be7c2 100644
--- a/cli/tests/integration_tests.rs
+++ b/cli/tests/integration_tests.rs
@@ -326,10 +326,166 @@ fn bundle_single_module() {
assert_eq!(output.stderr, b"");
}
-// TODO(#2933): Rewrite this test in rust.
#[test]
-fn repl_test() {
- util::run_python_script("tools/repl_test.py")
+fn repl_test_console_log() {
+ let (out, err, code) =
+ util::repl_process(vec!["console.log('hello')", "'world'"], None);
+ assert_eq!(out, "hello\nundefined\nworld\n");
+ assert!(err.is_empty());
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_eof() {
+ // test_eof
+ let (out, err, code) = util::repl_process(vec!["1 + 2"], None);
+ assert_eq!(out, "3\n");
+ assert!(err.is_empty());
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_exit_command() {
+ let (out, err, code) = util::repl_process(vec!["exit", "'ignored'"], None);
+ assert!(out.is_empty());
+ assert!(err.is_empty());
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_help_command() {
+ let (out, err, code) = util::repl_process(vec!["help"], None);
+ assert_eq!(
+ out,
+ vec![
+ "_ Get last evaluation result",
+ "_error Get last thrown error",
+ "exit Exit the REPL",
+ "help Print this help message",
+ "",
+ ]
+ .join("\n")
+ );
+ assert!(err.is_empty());
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_function() {
+ let (out, err, code) = util::repl_process(vec!["Deno.writeFileSync"], None);
+ assert_eq!(out, "[Function: writeFileSync]\n");
+ assert!(err.is_empty());
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_multiline() {
+ let (out, err, code) = util::repl_process(vec!["(\n1 + 2\n)"], None);
+ assert_eq!(out, "3\n");
+ assert!(err.is_empty());
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_eval_unterminated() {
+ let (out, err, code) = util::repl_process(vec!["eval('{')"], None);
+ assert!(out.is_empty());
+ assert!(err.contains("Unexpected end of input"));
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_reference_error() {
+ let (out, err, code) = util::repl_process(vec!["not_a_variable"], None);
+ assert!(out.is_empty());
+ assert!(err.contains("not_a_variable is not defined"));
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_syntax_error() {
+ let (out, err, code) = util::repl_process(vec!["syntax error"], None);
+ assert!(out.is_empty());
+ assert!(err.contains("Unexpected identifier"));
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_type_error() {
+ let (out, err, code) = util::repl_process(vec!["console()"], None);
+ assert!(out.is_empty());
+ assert!(err.contains("console is not a function"));
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_variable() {
+ let (out, err, code) = util::repl_process(vec!["var a = 123;", "a"], None);
+ assert_eq!(out, "undefined\n123\n");
+ assert!(err.is_empty());
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_lexical_scoped_variable() {
+ let (out, err, code) = util::repl_process(vec!["let a = 123;", "a"], None);
+ assert_eq!(out, "undefined\n123\n");
+ assert!(err.is_empty());
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_missing_deno_dir() {
+ use std::fs::{read_dir, remove_dir_all};
+ const DENO_DIR: &str = "nonexistent";
+ let (out, err, code) = util::repl_process(
+ vec!["1"],
+ Some(vec![("DENO_DIR".to_owned(), DENO_DIR.to_owned())]),
+ );
+ assert!(read_dir(DENO_DIR).is_ok());
+ remove_dir_all(DENO_DIR).unwrap();
+ assert_eq!(out, "1\n");
+ assert!(err.is_empty());
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_save_last_eval() {
+ let (out, err, code) = util::repl_process(vec!["1", "_"], None);
+ assert_eq!(out, "1\n1\n");
+ assert!(err.is_empty());
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_save_last_thrown() {
+ let (out, err, code) = util::repl_process(vec!["throw 1", "_error"], None);
+ assert_eq!(out, "1\n");
+ assert_eq!(err, "Thrown: 1\n");
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_assign_underscore() {
+ let (out, err, code) = util::repl_process(vec!["_ = 1", "2", "_"], None);
+ assert_eq!(
+ out,
+ "Last evaluation result is no longer saved to _.\n1\n2\n1\n"
+ );
+ assert!(err.is_empty());
+ assert_eq!(code, 0);
+}
+
+#[test]
+fn repl_test_assign_underscore_error() {
+ let (out, err, code) =
+ util::repl_process(vec!["_error = 1", "throw 2", "_error"], None);
+ assert_eq!(
+ out,
+ "Last thrown error is no longer saved to _error.\n1\n1\n"
+ );
+ assert_eq!(err, "Thrown: 2\n");
+ assert_eq!(code, 0);
}
#[test]
@@ -1164,6 +1320,7 @@ mod util {
use std::io::Read;
use std::io::Write;
use std::process::Command;
+ use std::process::Output;
use std::process::Stdio;
use tempfile::TempDir;
@@ -1171,6 +1328,39 @@ mod util {
static ref DENO_DIR: TempDir = { TempDir::new().expect("tempdir fail") };
}
+ pub fn repl_process(
+ lines: Vec<&str>,
+ envs: Option<Vec<(String, String)>>,
+ ) -> (String, String, i32) {
+ let mut deno_process_builder = deno_cmd();
+ deno_process_builder
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .stderr(Stdio::piped());
+ if let Some(envs) = envs {
+ deno_process_builder.envs(envs);
+ }
+ let mut deno = deno_process_builder
+ .spawn()
+ .expect("failed to spawn script");
+ {
+ let stdin = deno.stdin.as_mut().expect("failed to get stdin");
+ stdin
+ .write_all(lines.join("\n").as_bytes())
+ .expect("failed to write to stdin");
+ }
+ let Output {
+ stdout,
+ stderr,
+ status,
+ } = deno.wait_with_output().expect("failed to wait on child");
+ (
+ String::from_utf8(stdout).unwrap(),
+ String::from_utf8(stderr).unwrap(),
+ status.code().unwrap(),
+ )
+ }
+
pub fn deno_cmd() -> Command {
let mut c = Command::new(deno_exe_path());
c.env("DENO_DIR", DENO_DIR.path());
diff --git a/tools/repl_test.py b/tools/repl_test.py
deleted file mode 100644
index aae8a558f..000000000
--- a/tools/repl_test.py
+++ /dev/null
@@ -1,187 +0,0 @@
-# Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import os
-import shutil
-from subprocess import CalledProcessError, PIPE, Popen
-import sys
-import time
-
-from test_util import DenoTestCase, run_tests
-
-
-class TestRepl(DenoTestCase):
- def input(self, *lines, **kwargs):
- exit_ = kwargs.pop("exit", True)
- sleep_ = kwargs.pop("sleep", 0)
- env_ = kwargs.pop("env", None)
- p = Popen([self.deno_exe],
- stdout=PIPE,
- stderr=PIPE,
- stdin=PIPE,
- env=env_)
- try:
- # Note: The repl takes a >100ms until it's ready.
- time.sleep(sleep_)
- for line in lines:
- p.stdin.write(line.encode("utf-8") + b'\n')
- p.stdin.flush()
- time.sleep(sleep_)
- if exit_:
- p.stdin.write(b'Deno.exit(0)\n')
- else:
- time.sleep(1) # wait to be killed by js
- out, err = p.communicate()
- except CalledProcessError as e:
- p.kill()
- p.wait()
- raise e
- retcode = p.poll()
- # Ignore Windows CRLF (\r\n).
- return out.replace('\r\n', '\n'), err.replace('\r\n', '\n'), retcode
-
- def test_console_log(self):
- out, err, code = self.input("console.log('hello')", "'world'")
- self.assertEqual(out, 'hello\nundefined\nworld\n')
- self.assertEqual(err, '')
- self.assertEqual(code, 0)
-
- def test_eof(self):
- out, err, code = self.input("1 + 2", exit=False)
- self.assertEqual(out, '3\n')
- self.assertEqual(err, '')
- self.assertEqual(code, 0)
-
- def test_exit_command(self):
- out, err, code = self.input("exit", "'ignored'", exit=False)
- self.assertEqual(out, '')
- self.assertEqual(err, '')
- self.assertEqual(code, 0)
-
- def test_help_command(self):
- out, err, code = self.input("help")
- expectedOut = '\n'.join([
- "_ Get last evaluation result",
- "_error Get last thrown error",
- "exit Exit the REPL",
- "help Print this help message",
- "",
- ])
- self.assertEqual(out, expectedOut)
- self.assertEqual(err, '')
- self.assertEqual(code, 0)
-
- def test_function(self):
- out, err, code = self.input("Deno.writeFileSync")
- self.assertEqual(out, '[Function: writeFileSync]\n')
- self.assertEqual(err, '')
- self.assertEqual(code, 0)
-
- def test_multiline(self):
- out, err, code = self.input("(\n1 + 2\n)")
- self.assertEqual(out, '3\n')
- self.assertEqual(err, '')
- self.assertEqual(code, 0)
-
- # This should print error instead of wait for input
- def test_eval_unterminated(self):
- out, err, code = self.input("eval('{')")
- self.assertEqual(out, '')
- assert "Unexpected end of input" in err
- self.assertEqual(code, 0)
-
- def test_reference_error(self):
- out, err, code = self.input("not_a_variable")
- self.assertEqual(out, '')
- assert "not_a_variable is not defined" in err
- self.assertEqual(code, 0)
-
- # def test_set_timeout(self):
- # out, err, code = self.input(
- # "setTimeout(() => { console.log('b'); Deno.exit(0); }, 1)",
- # "'a'",
- # exit=False)
- # self.assertEqual(out, '1\na\nb\n')
- # self.assertEqual(err, '')
- # self.assertEqual(code, 0)
-
- # def test_set_timeout_interlaced(self):
- # out, err, code = self.input(
- # "setTimeout(() => console.log('a'), 1)",
- # "setTimeout(() => console.log('b'), 6)",
- # sleep=0.8)
- # self.assertEqual(out, '1\n2\na\nb\n')
- # self.assertEqual(err, '')
- # self.assertEqual(code, 0)
-
- # def test_async_op(self):
- # out, err, code = self.input(
- # "fetch('http://localhost:4545/cli/tests/001_hello.js')" +
- # ".then(res => res.text()).then(console.log)",
- # sleep=1)
- # self.assertEqual(out, 'Promise {}\nconsole.log("Hello World");\n\n')
- # self.assertEqual(err, '')
- # self.assertEqual(code, 0)
-
- def test_syntax_error(self):
- out, err, code = self.input("syntax error")
- self.assertEqual(out, '')
- assert "Unexpected identifier" in err
- self.assertEqual(code, 0)
-
- def test_type_error(self):
- out, err, code = self.input("console()")
- self.assertEqual(out, '')
- assert "console is not a function" in err
- self.assertEqual(code, 0)
-
- def test_variable(self):
- out, err, code = self.input("var a = 123;", "a")
- self.assertEqual(out, 'undefined\n123\n')
- self.assertEqual(err, '')
- self.assertEqual(code, 0)
-
- def test_lexical_scoped_variable(self):
- out, err, code = self.input("let a = 123;", "a")
- self.assertEqual(out, 'undefined\n123\n')
- self.assertEqual(err, '')
- self.assertEqual(code, 0)
-
- def test_missing_deno_dir(self):
- deno_dir = "nonexistent"
- new_env = os.environ.copy()
- new_env["DENO_DIR"] = deno_dir
- out, err, code = self.input("1", exit=False, env=new_env)
- self.assertTrue(os.path.isdir(deno_dir))
- shutil.rmtree(deno_dir)
- self.assertEqual(out, "1\n")
- self.assertEqual(err, "")
- self.assertEqual(code, 0)
-
- def test_save_last_eval(self):
- out, err, code = self.input("1", "_")
- self.assertEqual(out, '1\n1\n')
- self.assertEqual(err, '')
- self.assertEqual(code, 0)
-
- def test_save_last_thrown(self):
- out, err, code = self.input("throw 1", "_error")
- self.assertEqual(out, '1\n')
- self.assertEqual(err, 'Thrown: 1\n')
- self.assertEqual(code, 0)
-
- def test_assign_underscore(self):
- out, err, code = self.input("_ = 1", "2", "_")
- self.assertEqual(
- out, 'Last evaluation result is no longer saved to _.\n1\n2\n1\n')
- self.assertEqual(err, '')
- self.assertEqual(code, 0)
-
- def test_assign_underscore_error(self):
- out, err, code = self.input("_error = 1", "throw 2", "_error")
- self.assertEqual(
- out, 'Last thrown error is no longer saved to _error.\n1\n1\n')
- self.assertEqual(err, 'Thrown: 2\n')
- self.assertEqual(code, 0)
-
-
-if __name__ == "__main__":
- run_tests()