1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! Helpers for testing implementations of the async-codec traits.

use std::fmt::Debug;

use async_codec::{AsyncDecode, DecodeError, AsyncEncode, AsyncEncodeLen};
use futures_io::{AsyncRead, AsyncWrite};
use futures_io::ErrorKind::{UnexpectedEof, WriteZero};
use futures_executor::block_on;
use futures_util::FutureExt;

use super::{decode, encode};

/// Returns whether the given decoder returns an error of kind `UnexpectedEof` when trying to fully
/// decode from the given reader.
pub fn unexpected_eof_errors<R: AsyncRead, D: AsyncDecode<R>>(reader: R, dec: D) -> bool {
    match block_on(decode(reader, dec)) {
        Ok(_) => false,
        Err((_, err)) => {
            match err {
                DecodeError::ReaderError(err) => err.kind() == UnexpectedEof,
                DecodeError::DataError(_) => false,
            }
        }
    }
}

/// Returns whether the given encoder returns an error of kind `WriteZero` when trying to fully
/// encode into the given writer.
pub fn write_zero_errors<W: AsyncWrite, C: AsyncEncode<W>>(writer: W, co: C) -> bool {
    match block_on(encode(writer, co)) {
        Ok(_) => false,
        Err((_, err)) => err.kind() == WriteZero,
    }
}

fn test_codec_intern<R: AsyncRead, W: AsyncWrite, D: AsyncDecode<R>, C: AsyncEncode<W>>
    (reader: R,
     writer: W,
     dec: D,
     co: C)
     -> (D::Item, usize, usize)
    where D::Error: Debug
{
    let c = encode(writer, co);
    let d = decode(reader, dec);

    let c = c.map(|(_, written)| (None, written))
        .map_err(|(_, err)| panic!("{:?}", err));
    let d = d.map(|(_, item, read)| (Some(item), read))
        .map_err(|(_, err)| panic!("{:?}", err));
    block_on(c.join(d)
                 .map(|((_, written), (item, read)): ((Option<D::Item>, usize),
                                                      (Option<D::Item>, usize))| {
                          let item = item.unwrap();
                          (item, written, read)
                      }))
            .map_err(|_| unreachable!())
            .unwrap()
}

/// Run an encoder and a decoder concurrently, returning the decoded output and whether the encoder
/// produced as many bytes as the decoder consumed.
pub fn test_codec<R: AsyncRead, W: AsyncWrite, D: AsyncDecode<R>, C: AsyncEncode<W>>
    (reader: R,
     writer: W,
     dec: D,
     co: C)
     -> (D::Item, bool)
    where D::Error: Debug
{
    let (item, written, read) = test_codec_intern(reader, writer, dec, co);
    (item, written == read)
}

/// Run an encoder and a decoder concurrently, returning the decoded output and whether the encoder
/// produced as many bytes as it promised and as the decoder consumed.
pub fn test_codec_len<R: AsyncRead, W: AsyncWrite, D: AsyncDecode<R>, C: AsyncEncodeLen<W>>
    (reader: R,
     writer: W,
     dec: D,
     co: C)
     -> (D::Item, bool)
    where D::Error: Debug
{
    let expected_len = co.remaining_bytes();
    let (item, written, read) = test_codec_intern(reader, writer, dec, co);
    (item, written == read && written == expected_len)
}