proptest_arbitrary/_std/
io.rs

1//! Arbitrary implementations for `std::io`.
2
3use super::*;
4use std::io::*;
5use std::io::ErrorKind::*;
6
7// TODO: IntoInnerError
8// Consider: std::io::Initializer
9
10macro_rules! buffer {
11    ($type: ident, $bound: path) => {
12        arbitrary!(
13            [A: Arbitrary<'a> + $bound] $type<A>,
14            SMapped<'a, (A, Option<u16>), Self>, A::Parameters;
15            args => any_with_smap(product_pack![args, default()], |(inner, cap)|
16                if let Some(cap) = cap {
17                    $type::with_capacity(cap as usize, inner)
18                } else {
19                    $type::new(inner)
20                }
21            )
22        );
23    };
24}
25
26buffer!(BufReader,  Read);
27buffer!(BufWriter,  Write);
28buffer!(LineWriter, Write);
29
30arbitrary!(
31    [A: Read + Arbitrary<'a>, B: Read + Arbitrary<'a>] Chain<A, B>,
32    SMapped<'a, (A, B), Self>, product_type![A::Parameters, B::Parameters];
33    args => any_with_smap(args, |(a, b)| a.chain(b))
34);
35
36wrap_ctor!(Cursor);
37
38generator!(
39      Empty, empty
40    ; Sink, sink
41    ; Stderr, stderr
42    ; Stdin, stdin
43    ; Stdout, stdout
44);
45
46wrap_ctor!([BufRead] Lines, BufRead::lines);
47
48arbitrary!(Repeat, SMapped<'a, u8, Self>; any_with_smap((), repeat));
49
50arbitrary!(
51    [A: BufRead + Arbitrary<'a>] Split<A>,
52    SMapped<'a, (A, u8), Self>, A::Parameters;
53    args => any_with_smap(product_pack![args, default()], |(a, b)| a.split(b))
54);
55
56arbitrary!(
57    [A: Read + Arbitrary<'a>] Take<A>,
58    SMapped<'a, (A, u64), Self>, A::Parameters;
59    args => any_with_smap(product_pack![args, default()], |(a, b)| a.take(b))
60);
61
62#[cfg(feature = "unstable")]
63wrap_ctor!([Read] Chars, Read::chars);
64
65arbitrary!(ErrorKind, Union<Just<Self>>;
66    Union::new(
67    [ NotFound
68    , PermissionDenied
69    , ConnectionRefused
70    , ConnectionReset
71    , ConnectionAborted
72    , NotConnected
73    , AddrInUse
74    , AddrNotAvailable
75    , BrokenPipe
76    , AlreadyExists
77    , WouldBlock
78    , InvalidInput
79    , InvalidData
80    , TimedOut
81    , WriteZero
82    , Interrupted
83    , Other
84    , UnexpectedEof
85    // TODO: watch this type for variant-additions.
86    ].into_iter().map(Clone::clone).map(Just))
87);
88
89arbitrary!(
90    SeekFrom,
91    TupleUnion<(
92        W<SMapped<'a, u64, SeekFrom>>,
93        W<SMapped<'a, i64, SeekFrom>>,
94        W<SMapped<'a, i64, SeekFrom>>,
95    )>;
96    prop_oneof![
97        static_map(any::<u64>(), SeekFrom::Start),
98        static_map(any::<i64>(), SeekFrom::End),
99        static_map(any::<i64>(), SeekFrom::Current)
100    ]
101);
102
103arbitrary!(Error, SMapped<'a, (ErrorKind, Option<String>), Self>;
104    any_with_smap(default(), |(k, os)|
105        if let Some(s) = os { Error::new(k, s) } else { k.into() }
106    )
107);
108
109#[cfg(feature = "unstable")]
110arbitrary!(CharsError, SMapped<'a, Option<Error>, Self>;
111    any_with_smap(default(), |oe| {
112        use std::io::CharsError::*;
113        if let Some(e) = oe { Other(e) } else { NotUtf8 }
114    })
115);
116
117#[cfg(test)]
118mod test {
119    no_panic_test!(
120        buf_reader  => BufReader<Repeat>,
121        buf_writer  => BufWriter<Sink>,
122        line_writer => LineWriter<Sink>,
123        chain       => Chain<Empty, BufReader<Repeat>>,
124        cursor      => Cursor<Empty>,
125        empty       => Empty,
126        sink        => Sink,
127        stderr      => Stderr,
128        stdin       => Stdin,
129        stdout      => Stdout,
130        lines       => Lines<Empty>,
131        repeat      => Repeat,
132        spit        => Split<Cursor<Vec<u8>>>,
133        take        => Take<Repeat>,
134        error_kind  => ErrorKind,
135        seek_from   => SeekFrom,
136        error       => Error
137    );
138
139    #[cfg(feature = "unstable")]
140    no_panic_test!(
141        chars       => Chars<Repeat>,
142        chars_error => CharsError
143    );
144}