use std::{ io::{BufRead, BufReader, Read, Write}, net::TcpStream, path::Path, process::{Child, Command, Stdio}, }; struct Server(Child); impl Drop for Server { fn drop(&mut self) { let _ = self.0.kill(); let _ = self.0.wait(); } } fn start(root: &Path, socket: Option<&Path>) -> (Server, String) { let mut command = Command::new(env!("CARGO_BIN_EXE_serve-esm")); command.env("TARGET_DIR", root).env_remove("SOCKET_PATH"); command.env("LISTEN", "127.0.0.1:0").stderr(Stdio::piped()); if let Some(socket) = socket { command.env("SOCKET_PATH", socket); } let mut server = Server(command.spawn().unwrap()); let mut line = String::new(); BufReader::new(server.0.stderr.take().unwrap()) .read_line(&mut line) .unwrap(); let address = line .trim() .strip_prefix("listening on ") .expect(&line) .to_owned(); (server, address) } fn request(mut stream: impl Read + Write) { stream .write_all(b"GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n") .unwrap(); let mut response = String::new(); stream.read_to_string(&mut response).unwrap(); assert!(response.starts_with("HTTP/1.1 404"), "{response}"); assert!(response.ends_with("\r\n\r\nnot found"), "{response}"); } #[test] fn tcp_and_unix_listeners() { let root = tempfile::tempdir().unwrap(); let (_server, address) = start(root.path(), None); request(TcpStream::connect(address.strip_prefix("http://").unwrap()).unwrap()); let socket = root.path().join("serve-esm.sock"); let (_unix_server, _) = start(root.path(), Some(&socket)); request(std::os::unix::net::UnixStream::connect(socket).unwrap()); }