async_codec_util/
testing.rs

1//! Helpers for testing implementations of the async-codec traits.
2
3use std::fmt::Debug;
4
5use async_codec::{AsyncDecode, DecodeError, AsyncEncode, AsyncEncodeLen};
6use futures_io::{AsyncRead, AsyncWrite};
7use futures_io::ErrorKind::{UnexpectedEof, WriteZero};
8use futures_executor::block_on;
9use futures_util::FutureExt;
10
11use super::{decode, encode};
12
13/// Returns whether the given decoder returns an error of kind `UnexpectedEof` when trying to fully
14/// decode from the given reader.
15pub fn unexpected_eof_errors<R: AsyncRead, D: AsyncDecode>(reader: R, dec: D) -> bool {
16    match block_on(decode(reader, dec)) {
17        Ok(_) => false,
18        Err((_, err)) => {
19            match err {
20                DecodeError::ReaderError(err) => err.kind() == UnexpectedEof,
21                DecodeError::DataError(_) => false,
22            }
23        }
24    }
25}
26
27/// Returns whether the given encoder returns an error of kind `WriteZero` when trying to fully
28/// encode into the given writer.
29pub fn write_zero_errors<W: AsyncWrite, C: AsyncEncode>(writer: W, co: C) -> bool {
30    match block_on(encode(writer, co)) {
31        Ok(_) => false,
32        Err((_, err)) => err.kind() == WriteZero,
33    }
34}
35
36fn test_codec_intern<R: AsyncRead, W: AsyncWrite, D: AsyncDecode, C: AsyncEncode>
37    (reader: R,
38     writer: W,
39     dec: D,
40     co: C)
41     -> (D::Item, usize, usize)
42    where D::Error: Debug
43{
44    let c = encode(writer, co);
45    let d = decode(reader, dec);
46
47    let c = c.map(|(_, written)| (None, written))
48        .map_err(|(_, err)| panic!("{:?}", err));
49    let d = d.map(|(_, item, read)| (Some(item), read))
50        .map_err(|(_, err)| panic!("{:?}", err));
51    block_on(c.join(d)
52                 .map(|((_, written), (item, read)): ((Option<D::Item>, usize),
53                                                      (Option<D::Item>, usize))| {
54                          let item = item.unwrap();
55                          (item, written, read)
56                      }))
57            .map_err(|_| unreachable!())
58            .unwrap()
59}
60
61/// Run an encoder and a decoder concurrently, returning the decoded output and whether the encoder
62/// produced as many bytes as the decoder consumed.
63pub fn test_codec<R: AsyncRead, W: AsyncWrite, D: AsyncDecode, C: AsyncEncode>(reader: R,
64                                                                               writer: W,
65                                                                               dec: D,
66                                                                               co: C)
67                                                                               -> (D::Item, bool)
68    where D::Error: Debug
69{
70    let (item, written, read) = test_codec_intern(reader, writer, dec, co);
71    (item, written == read)
72}
73
74/// Run an encoder and a decoder concurrently, returning the decoded output and whether the encoder
75/// produced as many bytes as it promised and as the decoder consumed.
76pub fn test_codec_len<R: AsyncRead, W: AsyncWrite, D: AsyncDecode, C: AsyncEncodeLen>
77    (reader: R,
78     writer: W,
79     dec: D,
80     co: C)
81     -> (D::Item, bool)
82    where D::Error: Debug
83{
84    let expected_len = co.remaining_bytes();
85    let (item, written, read) = test_codec_intern(reader, writer, dec, co);
86    (item, written == read && written == expected_len)
87}