fix socket connection problems

This commit is contained in:
Shunsuke Shibayama 2023-01-25 01:19:45 +09:00
parent fa5bb4f615
commit b76d63f9a5
6 changed files with 52 additions and 30 deletions

View file

@ -74,13 +74,15 @@ impl fmt::Display for ErgMode {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DummyStdin {
pub name: String,
current_line: usize,
lines: Vec<String>,
}
impl DummyStdin {
pub fn new(lines: Vec<String>) -> Self {
pub fn new(name: String, lines: Vec<String>) -> Self {
Self {
name,
current_line: 0,
lines,
}
@ -160,7 +162,8 @@ impl Input {
pub fn filename(&self) -> &str {
match self {
Self::File(filename) => filename.file_name().and_then(|f| f.to_str()).unwrap_or("_"),
Self::REPL | Self::DummyREPL(_) | Self::Pipe(_) => "stdin",
Self::REPL | Self::Pipe(_) => "stdin",
Self::DummyREPL(stdin) => &stdin.name,
Self::Str(_) => "string",
Self::Dummy => "dummy",
}

View file

@ -1,5 +1,6 @@
//! defines the compiler for Erg (ergc).
#![allow(clippy::large_enum_variant)]
#![allow(clippy::result_large_err)]
extern crate erg_common;
pub extern crate erg_parser;

View file

@ -61,7 +61,8 @@ impl Runnable for DummyVM {
}
let port = find_available_port();
let code = include_str!("scripts/repl_server.py")
.replace("__PORT__", port.to_string().as_str());
.replace("__PORT__", port.to_string().as_str())
.replace("__MODULE__", &cfg.dump_filename());
spawn_py(cfg.py_command, &code);
let addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, port);
if !cfg.quiet_repl {
@ -112,7 +113,7 @@ impl Runnable for DummyVM {
process::exit(1);
}
}
remove_file("o.pyc").unwrap_or(());
remove_file(self.cfg().dump_pyc_filename()).unwrap_or(());
}
}
@ -142,9 +143,10 @@ impl Runnable for DummyVM {
}
fn eval(&mut self, src: String) -> Result<String, EvalErrors> {
let path = self.cfg().dump_pyc_filename();
let arti = self
.compiler
.eval_compile_and_dump_as_pyc("o.pyc", src, "eval")
.eval_compile_and_dump_as_pyc(path, src, "eval")
.map_err(|eart| eart.errors)?;
let (last, warns) = (arti.object, arti.warns);
let mut res = warns.to_string();
@ -207,17 +209,23 @@ impl DummyVM {
}
}
#[cfg(test)]
fn find_available_port() -> u16 {
require_free_port()
}
#[cfg(not(test))]
fn find_available_port() -> u16 {
const DEFAULT_PORT: u16 = 8736;
TcpListener::bind(SocketAddrV4::new(Ipv4Addr::LOCALHOST, DEFAULT_PORT))
.is_ok()
.then_some(DEFAULT_PORT)
.unwrap_or_else(|| {
// localhost:0 will bind to a free port
.unwrap_or_else(require_free_port)
}
fn require_free_port() -> u16 {
let socket = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0);
TcpListener::bind(socket)
.and_then(|listener| listener.local_addr())
.map(|sock_addr| sock_addr.port())
.expect("No free port found.")
})
}

View file

@ -28,9 +28,10 @@ while True:
__sys.stdout = __io.StringIO()
try:
if __already_loaded:
__res = str(exec('__importlib.reload(o)'))
# __MODULE__ will be replaced with module name
__res = str(exec('__importlib.reload(__MODULE__)'))
else:
__res = str(exec('import o'))
__res = str(exec('import __MODULE__'))
except SystemExit:
__client_socket.send('[Exception] SystemExit'.encode())
continue

View file

@ -12,8 +12,8 @@ use erg_compiler::error::CompileErrors;
use erg::DummyVM;
pub(crate) fn expect_repl_success(lines: Vec<String>) -> Result<(), ()> {
match exec_repl(lines) {
pub(crate) fn expect_repl_success(name: &'static str, lines: Vec<String>) -> Result<(), ()> {
match exec_repl(name, lines) {
Ok(ExitStatus::OK) => Ok(()),
Ok(stat) => {
println!("err: should succeed, but got: {stat:?}");
@ -114,10 +114,10 @@ fn _exec_file(file_path: &'static str) -> Result<i32, CompileErrors> {
}
/// WARN: You must quit REPL manually (use `:exit`, `:quit` or call something shutdowns the interpreter)
pub fn _exec_repl(lines: Vec<String>) -> Result<ExitStatus, CompileErrors> {
pub fn _exec_repl(name: &'static str, lines: Vec<String>) -> Result<ExitStatus, CompileErrors> {
println!("{GREEN}[test] exec dummy REPL: {lines:?}{RESET}");
let cfg = ErgConfig {
input: Input::DummyREPL(DummyStdin::new(lines)),
input: Input::DummyREPL(DummyStdin::new(name.to_string(), lines)),
quiet_repl: true,
..Default::default()
};
@ -129,6 +129,9 @@ pub(crate) fn exec_file(file_path: &'static str) -> Result<i32, CompileErrors> {
exec_new_thread(move || _exec_file(file_path))
}
pub(crate) fn exec_repl(lines: Vec<String>) -> Result<ExitStatus, CompileErrors> {
exec_new_thread(move || _exec_repl(lines))
pub(crate) fn exec_repl(
name: &'static str,
lines: Vec<String>,
) -> Result<ExitStatus, CompileErrors> {
exec_new_thread(move || _exec_repl(name, lines))
}

View file

@ -3,17 +3,23 @@ use common::expect_repl_success;
#[test]
fn exec_repl_helloworld() -> Result<(), ()> {
expect_repl_success(vec!["print! \"hello, world\"".into(), "exit()".into()])
expect_repl_success(
"repl_hello",
vec!["print! \"hello, world\"".into(), "exit()".into()],
)
}
#[test]
fn exec_repl_def_func() -> Result<(), ()> {
expect_repl_success(vec![
expect_repl_success(
"repl_def",
vec![
"f i =".into(),
" i + 1".into(),
"".into(),
"x = f 2".into(),
"assert x == 3".into(),
"exit()".into(),
])
],
)
}