|
|
|
@ -6,12 +6,49 @@
|
|
|
|
|
// option. All files in the project carrying such notice may not be copied,
|
|
|
|
|
// modified, or distributed except according to those terms.
|
|
|
|
|
|
|
|
|
|
use std::io::{self, BufRead, BufReader, BufWriter, Write};
|
|
|
|
|
use std::io::{self, BufRead, BufReader, BufWriter, Read, Write};
|
|
|
|
|
use std::path::Path;
|
|
|
|
|
use std::thread;
|
|
|
|
|
|
|
|
|
|
use std::os::unix::net::UnixListener;
|
|
|
|
|
|
|
|
|
|
/// Split lines on CRLF
|
|
|
|
|
fn split_lines(lines: &str) -> Vec<String> {
|
|
|
|
|
lines
|
|
|
|
|
.trim_end()
|
|
|
|
|
.split("\r\n")
|
|
|
|
|
.map(|s| format!("{}\r\n", s))
|
|
|
|
|
.collect::<Vec<String>>()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Handle the communication for tests.
|
|
|
|
|
///
|
|
|
|
|
/// The communication is a list of (question, answer). If the client sends the expected question
|
|
|
|
|
/// in the sequence, the answer is returned.
|
|
|
|
|
fn serve_streams(
|
|
|
|
|
instream: &mut dyn Read,
|
|
|
|
|
outstream: &mut dyn Write,
|
|
|
|
|
communication: &[(&'static str, &'static str)],
|
|
|
|
|
) -> io::Result<()> {
|
|
|
|
|
let mut input = BufReader::new(instream);
|
|
|
|
|
let mut output = BufWriter::new(outstream);
|
|
|
|
|
for (questions, answer) in communication.iter() {
|
|
|
|
|
for question in split_lines(questions).iter() {
|
|
|
|
|
let mut line = String::new();
|
|
|
|
|
input.read_line(&mut line)?;
|
|
|
|
|
if line != *question {
|
|
|
|
|
return Err(io::Error::new(
|
|
|
|
|
io::ErrorKind::InvalidInput,
|
|
|
|
|
format!("read <{}> instead of <{}>", line, *question),
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
output.write_all(answer.as_bytes())?;
|
|
|
|
|
output.flush()?;
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Server traits
|
|
|
|
|
pub trait Server {
|
|
|
|
|
fn serve(&mut self) -> io::Result<()>;
|
|
|
|
@ -41,36 +78,12 @@ impl UnixServer {
|
|
|
|
|
communication: communication.to_vec(),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn split_lines(lines: &str) -> Vec<String> {
|
|
|
|
|
lines
|
|
|
|
|
.trim_end()
|
|
|
|
|
.split("\r\n")
|
|
|
|
|
.map(|s| format!("{}\r\n", s))
|
|
|
|
|
.collect::<Vec<String>>()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Server for UnixServer {
|
|
|
|
|
fn serve(&mut self) -> io::Result<()> {
|
|
|
|
|
let (stream, _) = self.listener.accept()?;
|
|
|
|
|
let mut input = BufReader::new(stream.try_clone()?);
|
|
|
|
|
let mut output = BufWriter::new(stream);
|
|
|
|
|
for (questions, answer) in self.communication.iter() {
|
|
|
|
|
for question in Self::split_lines(questions).iter() {
|
|
|
|
|
let mut line = String::new();
|
|
|
|
|
input.read_line(&mut line)?;
|
|
|
|
|
if line != *question {
|
|
|
|
|
return Err(io::Error::new(
|
|
|
|
|
io::ErrorKind::InvalidInput,
|
|
|
|
|
format!("read <{}> instead of <{}>", line, *question),
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
output.write_all(answer.as_bytes())?;
|
|
|
|
|
output.flush()?;
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
let (mut stream, _) = self.listener.accept()?;
|
|
|
|
|
serve_streams(&mut stream.try_clone()?, &mut stream, &self.communication)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -98,12 +111,10 @@ where
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod test {
|
|
|
|
|
|
|
|
|
|
use super::UnixServer;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_split_lines() {
|
|
|
|
|
const ONE_LINE: &str = "one line\r\n";
|
|
|
|
|
let one_line = UnixServer::split_lines(ONE_LINE);
|
|
|
|
|
let one_line = super::split_lines(ONE_LINE);
|
|
|
|
|
assert_eq!(&[ONE_LINE], one_line.as_slice());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|