diff options
Diffstat (limited to 'tools/repl_test.py')
-rw-r--r-- | tools/repl_test.py | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/tools/repl_test.py b/tools/repl_test.py new file mode 100644 index 000000000..544dd6a7e --- /dev/null +++ b/tools/repl_test.py @@ -0,0 +1,183 @@ +# Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. +import os +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/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): + new_env = os.environ.copy() + new_env["DENO_DIR"] = os.path.abspath("doesnt_exist") + out, err, code = self.input("'noop'", exit=False, env=new_env) + self.assertEqual(out, "noop\n") + self.assertTrue(err.startswith("Unable to save REPL history:")) + 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() |