Registry testing - part 5
This commit is contained in:
@@ -245,23 +245,6 @@ pub async fn spam_training_samples(server: &Server) -> TrainingSamples {
|
||||
samples
|
||||
}
|
||||
|
||||
impl ImapConnection {
|
||||
async fn append(&mut self, mailbox: &str, message: &str) {
|
||||
self.send_ok(&format!(
|
||||
"APPEND {:?} {{{}+}}\r\n{}",
|
||||
mailbox,
|
||||
message.len(),
|
||||
message
|
||||
))
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn send_ok(&mut self, cmd: &str) {
|
||||
self.send(cmd).await;
|
||||
self.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
}
|
||||
}
|
||||
|
||||
pub const SPAM: [&str; 10] = [
|
||||
concat!(
|
||||
"Subject: save up to = on life insurance\r\n\r\n wh",
|
||||
|
||||
@@ -300,125 +300,6 @@ async fn init_imap_tests(delete_if_exists: bool) -> IMAPTest {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ImapConnection {
|
||||
tag: &'static [u8],
|
||||
reader: Lines<BufReader<ReadHalf<TcpStream>>>,
|
||||
writer: WriteHalf<TcpStream>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Type {
|
||||
Tagged,
|
||||
Untagged,
|
||||
Continuation,
|
||||
Status,
|
||||
}
|
||||
|
||||
impl ImapConnection {
|
||||
pub async fn connect(tag: &'static [u8]) -> Self {
|
||||
Self::connect_to(tag, "127.0.0.1:9991").await
|
||||
}
|
||||
|
||||
pub async fn connect_to(tag: &'static [u8], addr: impl AsRef<str>) -> Self {
|
||||
let (reader, writer) = tokio::io::split(TcpStream::connect(addr.as_ref()).await.unwrap());
|
||||
ImapConnection {
|
||||
tag,
|
||||
reader: BufReader::new(reader).lines(),
|
||||
writer,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn assert_read(&mut self, t: Type, rt: ResponseType) -> Vec<String> {
|
||||
let lines = self.read(t).await;
|
||||
let mut buf = Vec::with_capacity(10);
|
||||
buf.extend_from_slice(match t {
|
||||
Type::Tagged => self.tag,
|
||||
Type::Untagged | Type::Status => b"* ",
|
||||
Type::Continuation => b"+ ",
|
||||
});
|
||||
if !matches!(t, Type::Continuation | Type::Status) {
|
||||
rt.serialize(&mut buf);
|
||||
}
|
||||
if lines
|
||||
.last()
|
||||
.unwrap()
|
||||
.starts_with(&String::from_utf8(buf).unwrap())
|
||||
{
|
||||
lines
|
||||
} else {
|
||||
panic!("Expected {:?}/{:?} from server but got: {:?}", t, rt, lines);
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn assert_disconnect(&mut self) {
|
||||
match tokio::time::timeout(Duration::from_millis(1500), self.reader.next_line()).await {
|
||||
Ok(Ok(None)) => {}
|
||||
Ok(Ok(Some(line))) => {
|
||||
panic!("Expected connection to be closed, but got {:?}", line);
|
||||
}
|
||||
Ok(Err(err)) => {
|
||||
panic!("Connection broken: {:?}", err);
|
||||
}
|
||||
Err(_) => panic!("Timeout while waiting for server response."),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn read(&mut self, t: Type) -> Vec<String> {
|
||||
let mut lines = Vec::new();
|
||||
loop {
|
||||
match tokio::time::timeout(Duration::from_millis(1500), self.reader.next_line()).await {
|
||||
Ok(Ok(Some(line))) => {
|
||||
let is_done = line.starts_with(match t {
|
||||
Type::Tagged => std::str::from_utf8(self.tag).unwrap(),
|
||||
Type::Untagged | Type::Status => "* ",
|
||||
Type::Continuation => "+ ",
|
||||
});
|
||||
//let c = println!("<- {:?}", line);
|
||||
lines.push(line);
|
||||
if is_done {
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
Ok(Ok(None)) => {
|
||||
panic!("Invalid response: {:?}.", lines);
|
||||
}
|
||||
Ok(Err(err)) => {
|
||||
panic!("Connection broken: {} ({:?})", err, lines);
|
||||
}
|
||||
Err(_) => panic!("Timeout while waiting for server response: {:?}", lines),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn authenticate(&mut self, user: &str, pass: &str) {
|
||||
let creds = general_purpose::STANDARD.encode(format!("\0{user}\0{pass}"));
|
||||
self.send(&format!(
|
||||
"AUTHENTICATE PLAIN {{{}+}}\r\n{creds}",
|
||||
creds.len()
|
||||
))
|
||||
.await;
|
||||
self.assert_read(Type::Tagged, ResponseType::Ok).await;
|
||||
}
|
||||
|
||||
pub async fn send(&mut self, text: &str) {
|
||||
//let c = println!("-> {}{:?}", std::str::from_utf8(self.tag).unwrap(), text);
|
||||
self.writer.write_all(self.tag).await.unwrap();
|
||||
self.writer.write_all(text.as_bytes()).await.unwrap();
|
||||
self.writer.write_all(b"\r\n").await.unwrap();
|
||||
}
|
||||
|
||||
pub async fn send_untagged(&mut self, text: &str) {
|
||||
//let c = println!("-> {:?}", text);
|
||||
self.writer.write_all(text.as_bytes()).await.unwrap();
|
||||
self.writer.write_all(b"\r\n").await.unwrap();
|
||||
}
|
||||
|
||||
pub async fn send_raw(&mut self, text: &str) {
|
||||
//let c = println!("-> {:?}", text);
|
||||
self.writer.write_all(text.as_bytes()).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AssertResult: Sized {
|
||||
fn assert_folders<'x>(
|
||||
self,
|
||||
|
||||
@@ -187,91 +187,3 @@ pub async fn test() {
|
||||
.assert_contains("+OK 0 0");
|
||||
pop3.send("QUIT").await;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ResponseType {
|
||||
Ok,
|
||||
Multiline,
|
||||
Err,
|
||||
}
|
||||
|
||||
pub struct Pop3Connection {
|
||||
reader: Lines<BufReader<ReadHalf<TlsStream<TcpStream>>>>,
|
||||
writer: WriteHalf<TlsStream<TcpStream>>,
|
||||
}
|
||||
|
||||
impl Pop3Connection {
|
||||
pub async fn connect() -> Self {
|
||||
let (reader, writer) = tokio::io::split(
|
||||
build_tls_connector(true)
|
||||
.connect(
|
||||
ServerName::try_from("pop3.example.org").unwrap().to_owned(),
|
||||
TcpStream::connect("127.0.0.1:4110").await.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
);
|
||||
Pop3Connection {
|
||||
reader: BufReader::new(reader).lines(),
|
||||
writer,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn connect_and_login() -> Self {
|
||||
let mut pop3 = Self::connect().await;
|
||||
pop3.assert_read(ResponseType::Ok).await;
|
||||
pop3.send("AUTH PLAIN AHBvcHBlckBleGFtcGxlLmNvbQBzZWNyZXQ=")
|
||||
.await;
|
||||
pop3.assert_read(ResponseType::Ok).await;
|
||||
pop3
|
||||
}
|
||||
|
||||
pub async fn assert_read(&mut self, rt: ResponseType) -> Vec<String> {
|
||||
let lines = self.read(matches!(rt, ResponseType::Multiline)).await;
|
||||
if lines.last().unwrap().starts_with(match rt {
|
||||
ResponseType::Ok => "+OK",
|
||||
ResponseType::Multiline => ".",
|
||||
ResponseType::Err => "-ERR",
|
||||
}) {
|
||||
lines
|
||||
} else {
|
||||
panic!("Expected {:?} from server but got: {:?}", rt, lines);
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn read(&mut self, is_multiline: bool) -> Vec<String> {
|
||||
let mut lines = Vec::new();
|
||||
loop {
|
||||
match tokio::time::timeout(Duration::from_millis(1500), self.reader.next_line()).await {
|
||||
Ok(Ok(Some(line))) => {
|
||||
let is_done = (!is_multiline && line.starts_with("+OK"))
|
||||
|| (is_multiline && line == ".")
|
||||
|| line.starts_with("-ERR");
|
||||
//let c = println!("<- {:?}", line);
|
||||
lines.push(line);
|
||||
if is_done {
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
Ok(Ok(None)) => {
|
||||
panic!("Invalid response: {:?}.", lines);
|
||||
}
|
||||
Ok(Err(err)) => {
|
||||
panic!("Connection broken: {} ({:?})", err, lines);
|
||||
}
|
||||
Err(_) => panic!("Timeout while waiting for server response: {:?}", lines),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send(&mut self, text: &str) {
|
||||
//let c = println!("-> {:?}", text);
|
||||
self.writer.write_all(text.as_bytes()).await.unwrap();
|
||||
self.writer.write_all(b"\r\n").await.unwrap();
|
||||
}
|
||||
|
||||
pub async fn send_raw(&mut self, text: &str) {
|
||||
//let c = println!("-> {:?}", text);
|
||||
self.writer.write_all(text.as_bytes()).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user