Skip to content

Commit 7c0e244

Browse files
committed
Add regression test for v0.6.0 bug
Run as: cargo test --no-default-features --features=runtime-tokio large_fetch -- --nocapture
1 parent 1963ced commit 7c0e244

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

src/client.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2211,4 +2211,92 @@ mod tests {
22112211
}
22122212
panic!("No error");
22132213
}
2214+
2215+
/// Emulates a server responding to `FETCH` requests
2216+
/// with a body of 76 bytes of headers and N 74-byte lines,
2217+
/// where N is the requested message sequence number.
2218+
#[cfg(feature = "runtime-tokio")]
2219+
async fn handle_client(stream: tokio::io::DuplexStream) -> Result<()> {
2220+
use tokio::io::AsyncBufReadExt;
2221+
2222+
let (reader, mut writer) = tokio::io::split(stream);
2223+
let reader = tokio::io::BufReader::new(reader);
2224+
2225+
let mut lines = reader.lines();
2226+
while let Some(line) = lines.next_line().await? {
2227+
let (request_id, request) = line.split_once(' ').unwrap();
2228+
eprintln!("Received request {request_id}.");
2229+
2230+
let (id, _) = request
2231+
.strip_prefix("FETCH ")
2232+
.unwrap()
2233+
.split_once(' ')
2234+
.unwrap();
2235+
let id = id.parse().unwrap();
2236+
2237+
let mut body = concat!(
2238+
"From: Bob <[email protected]>\r\n",
2239+
"To: Alice <[email protected]>\r\n",
2240+
"Subject: Test\r\n",
2241+
"Message-Id: <[email protected]>\r\n",
2242+
"Date: Sun, 22 Mar 2020 00:00:00 +0100\r\n",
2243+
"\r\n",
2244+
)
2245+
.to_string();
2246+
for _ in 1..id {
2247+
body +=
2248+
"012345678901234567890123456789012345678901234567890123456789012345678901\r\n";
2249+
}
2250+
let body_len = body.len();
2251+
2252+
let response = format!("* {id} FETCH (RFC822.SIZE {body_len} BODY[] {{{body_len}}}\r\n{body} FLAGS (\\Seen))\r\n");
2253+
writer.write_all(response.as_bytes()).await?;
2254+
writer
2255+
.write_all(format!("{request_id} OK FETCH completed\r\n").as_bytes())
2256+
.await?;
2257+
writer.flush().await?;
2258+
}
2259+
2260+
Ok(())
2261+
}
2262+
2263+
/// Test requestng 1000 messages each larger than a previous one.
2264+
///
2265+
/// This is a regression test for v0.6.0 async-imap,
2266+
/// which sometimes failed to allocate free buffer space,
2267+
/// read into a buffer of zero size and erroneously detected it
2268+
/// as the end of stream.
2269+
#[cfg(feature = "runtime-tokio")]
2270+
#[cfg_attr(
2271+
feature = "runtime-tokio",
2272+
tokio::test(flavor = "multi_thread", worker_threads = 2)
2273+
)]
2274+
async fn large_fetch() -> Result<()> {
2275+
use futures::TryStreamExt;
2276+
2277+
let (client, server) = tokio::io::duplex(4096);
2278+
tokio::spawn(handle_client(server));
2279+
2280+
let client = crate::Client::new(client);
2281+
let mut imap_session = Session::new(client.conn);
2282+
2283+
for i in 200..300 {
2284+
eprintln!("Fetching {i}.");
2285+
let mut messages_stream = imap_session
2286+
.fetch(format!("{i}"), "(RFC822.SIZE BODY.PEEK[] FLAGS)")
2287+
.await?;
2288+
let fetch = messages_stream
2289+
.try_next()
2290+
.await?
2291+
.expect("no FETCH returned");
2292+
let body = fetch.body().expect("message did not have a body!");
2293+
assert_eq!(body.len(), 76 + 74 * i);
2294+
2295+
let no_fetch = messages_stream.try_next().await?;
2296+
assert!(no_fetch.is_none());
2297+
drop(messages_stream);
2298+
}
2299+
2300+
Ok(())
2301+
}
22142302
}

0 commit comments

Comments
 (0)