@@ -2211,4 +2211,92 @@ mod tests {
2211
2211
}
2212
2212
panic ! ( "No error" ) ;
2213
2213
}
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
+ }
2214
2302
}
0 commit comments