1 use {
2 super::{Arbitrary, Result, Unstructured},
3 std::{collections::HashSet, fmt::Debug, hash::Hash, rc::Rc, sync::Arc},
4 };
5
6 /// Assert that the given expected values are all generated.
7 ///
8 /// Exhaustively enumerates all buffers up to length 10 containing the
9 /// following bytes: `0x00`, `0x01`, `0x61` (aka ASCII 'a'), and `0xff`
assert_generates<T>(expected_values: impl IntoIterator<Item = T>) where T: Clone + Debug + Hash + Eq + for<'a> Arbitrary<'a>,10 fn assert_generates<T>(expected_values: impl IntoIterator<Item = T>)
11 where
12 T: Clone + Debug + Hash + Eq + for<'a> Arbitrary<'a>,
13 {
14 let expected_values: HashSet<_> = expected_values.into_iter().collect();
15 let mut arbitrary_expected = expected_values.clone();
16 let mut arbitrary_take_rest_expected = expected_values;
17
18 let bytes = [0, 1, b'a', 0xff];
19 let max_len = 10;
20
21 let mut buf = Vec::with_capacity(max_len);
22
23 let mut g = exhaustigen::Gen::new();
24 while !g.done() {
25 let len = g.gen(max_len);
26
27 buf.clear();
28 buf.extend(
29 std::iter::repeat_with(|| {
30 let index = g.gen(bytes.len() - 1);
31 bytes[index]
32 })
33 .take(len),
34 );
35
36 let mut u = Unstructured::new(&buf);
37 let val = T::arbitrary(&mut u).unwrap();
38 arbitrary_expected.remove(&val);
39
40 let u = Unstructured::new(&buf);
41 let val = T::arbitrary_take_rest(u).unwrap();
42 arbitrary_take_rest_expected.remove(&val);
43
44 if arbitrary_expected.is_empty() && arbitrary_take_rest_expected.is_empty() {
45 return;
46 }
47 }
48
49 panic!(
50 "failed to generate all expected values!\n\n\
51 T::arbitrary did not generate: {arbitrary_expected:#?}\n\n\
52 T::arbitrary_take_rest did not generate {arbitrary_take_rest_expected:#?}"
53 )
54 }
55
56 /// Generates an arbitrary `T`, and checks that the result is consistent with the
57 /// `size_hint()` reported by `T`.
checked_arbitrary<'a, T: Arbitrary<'a>>(u: &mut Unstructured<'a>) -> Result<T>58 fn checked_arbitrary<'a, T: Arbitrary<'a>>(u: &mut Unstructured<'a>) -> Result<T> {
59 let (min, max) = T::size_hint(0);
60
61 let len_before = u.len();
62 let result = T::arbitrary(u);
63
64 let consumed = len_before - u.len();
65
66 if let Some(max) = max {
67 assert!(
68 consumed <= max,
69 "incorrect maximum size: indicated {}, actually consumed {}",
70 max,
71 consumed
72 );
73 }
74
75 if result.is_ok() {
76 assert!(
77 consumed >= min,
78 "incorrect minimum size: indicated {}, actually consumed {}",
79 min,
80 consumed
81 );
82 }
83
84 result
85 }
86
87 /// Like `checked_arbitrary()`, but calls `arbitrary_take_rest()` instead of `arbitrary()`.
checked_arbitrary_take_rest<'a, T: Arbitrary<'a>>(u: Unstructured<'a>) -> Result<T>88 fn checked_arbitrary_take_rest<'a, T: Arbitrary<'a>>(u: Unstructured<'a>) -> Result<T> {
89 let (min, _) = T::size_hint(0);
90
91 let len_before = u.len();
92 let result = T::arbitrary_take_rest(u);
93
94 if result.is_ok() {
95 assert!(
96 len_before >= min,
97 "incorrect minimum size: indicated {}, worked with {}",
98 min,
99 len_before
100 );
101 }
102
103 result
104 }
105
106 #[test]
finite_buffer_fill_buffer()107 fn finite_buffer_fill_buffer() {
108 let x = [1, 2, 3, 4];
109 let mut rb = Unstructured::new(&x);
110 let mut z = [0; 2];
111 rb.fill_buffer(&mut z).unwrap();
112 assert_eq!(z, [1, 2]);
113 rb.fill_buffer(&mut z).unwrap();
114 assert_eq!(z, [3, 4]);
115 rb.fill_buffer(&mut z).unwrap();
116 assert_eq!(z, [0, 0]);
117 }
118
119 #[test]
arbitrary_for_integers()120 fn arbitrary_for_integers() {
121 let x = [1, 2, 3, 4];
122 let mut buf = Unstructured::new(&x);
123 let expected = 1 | (2 << 8) | (3 << 16) | (4 << 24);
124 let actual = checked_arbitrary::<i32>(&mut buf).unwrap();
125 assert_eq!(expected, actual);
126
127 assert_generates([
128 i32::from_ne_bytes([0, 0, 0, 0]),
129 i32::from_ne_bytes([0, 0, 0, 1]),
130 i32::from_ne_bytes([0, 0, 1, 0]),
131 i32::from_ne_bytes([0, 1, 0, 0]),
132 i32::from_ne_bytes([1, 0, 0, 0]),
133 i32::from_ne_bytes([1, 1, 1, 1]),
134 i32::from_ne_bytes([0xff, 0xff, 0xff, 0xff]),
135 ]);
136 }
137
138 #[test]
arbitrary_for_bytes()139 fn arbitrary_for_bytes() {
140 let x = [1, 2, 3, 4, 4];
141 let mut buf = Unstructured::new(&x);
142 let expected = &[1, 2, 3, 4];
143 let actual = checked_arbitrary::<&[u8]>(&mut buf).unwrap();
144 assert_eq!(expected, actual);
145 }
146
147 #[test]
arbitrary_take_rest_for_bytes()148 fn arbitrary_take_rest_for_bytes() {
149 let x = [1, 2, 3, 4];
150 let buf = Unstructured::new(&x);
151 let expected = &[1, 2, 3, 4];
152 let actual = checked_arbitrary_take_rest::<&[u8]>(buf).unwrap();
153 assert_eq!(expected, actual);
154 }
155
156 #[test]
arbitrary_for_vec_u8()157 fn arbitrary_for_vec_u8() {
158 assert_generates::<Vec<u8>>([
159 vec![],
160 vec![0],
161 vec![1],
162 vec![0, 0],
163 vec![0, 1],
164 vec![1, 0],
165 vec![1, 1],
166 vec![0, 0, 0],
167 vec![0, 0, 1],
168 vec![0, 1, 0],
169 vec![0, 1, 1],
170 vec![1, 0, 0],
171 vec![1, 0, 1],
172 vec![1, 1, 0],
173 vec![1, 1, 1],
174 ]);
175 }
176
177 #[test]
arbitrary_for_vec_vec_u8()178 fn arbitrary_for_vec_vec_u8() {
179 assert_generates::<Vec<Vec<u8>>>([
180 vec![],
181 vec![vec![]],
182 vec![vec![0]],
183 vec![vec![1]],
184 vec![vec![0, 1]],
185 vec![vec![], vec![]],
186 vec![vec![0], vec![]],
187 vec![vec![], vec![1]],
188 vec![vec![0], vec![1]],
189 vec![vec![0, 1], vec![]],
190 vec![vec![], vec![1, 0]],
191 vec![vec![], vec![], vec![]],
192 ]);
193 }
194
195 #[test]
arbitrary_for_vec_vec_vec_u8()196 fn arbitrary_for_vec_vec_vec_u8() {
197 assert_generates::<Vec<Vec<Vec<u8>>>>([
198 vec![],
199 vec![vec![]],
200 vec![vec![vec![0]]],
201 vec![vec![vec![1]]],
202 vec![vec![vec![0, 1]]],
203 vec![vec![], vec![]],
204 vec![vec![], vec![vec![]]],
205 vec![vec![vec![]], vec![]],
206 vec![vec![vec![]], vec![vec![]]],
207 vec![vec![vec![0]], vec![]],
208 vec![vec![], vec![vec![1]]],
209 vec![vec![vec![0]], vec![vec![1]]],
210 vec![vec![vec![0, 1]], vec![]],
211 vec![vec![], vec![vec![0, 1]]],
212 vec![vec![], vec![], vec![]],
213 vec![vec![vec![]], vec![], vec![]],
214 vec![vec![], vec![vec![]], vec![]],
215 vec![vec![], vec![], vec![vec![]]],
216 ]);
217 }
218
219 #[test]
arbitrary_for_string()220 fn arbitrary_for_string() {
221 assert_generates::<String>(["".into(), "a".into(), "aa".into(), "aaa".into()]);
222 }
223
224 #[test]
arbitrary_collection()225 fn arbitrary_collection() {
226 let x = [
227 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 12,
228 ];
229 assert_eq!(
230 checked_arbitrary::<&[u8]>(&mut Unstructured::new(&x)).unwrap(),
231 &[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3]
232 );
233 assert_eq!(
234 checked_arbitrary::<Vec<u8>>(&mut Unstructured::new(&x)).unwrap(),
235 &[2, 4, 6, 8, 1]
236 );
237 assert_eq!(
238 &*checked_arbitrary::<Box<[u8]>>(&mut Unstructured::new(&x)).unwrap(),
239 &[2, 4, 6, 8, 1]
240 );
241 assert_eq!(
242 &*checked_arbitrary::<Arc<[u8]>>(&mut Unstructured::new(&x)).unwrap(),
243 &[2, 4, 6, 8, 1]
244 );
245 assert_eq!(
246 &*checked_arbitrary::<Rc<[u8]>>(&mut Unstructured::new(&x)).unwrap(),
247 &[2, 4, 6, 8, 1]
248 );
249 assert_eq!(
250 checked_arbitrary::<Vec<u32>>(&mut Unstructured::new(&x)).unwrap(),
251 &[84148994]
252 );
253 assert_eq!(
254 checked_arbitrary::<String>(&mut Unstructured::new(&x)).unwrap(),
255 "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x01\x02\x03"
256 );
257 }
258
259 #[test]
arbitrary_take_rest()260 fn arbitrary_take_rest() {
261 // Basic examples
262 let x = [1, 2, 3, 4];
263 assert_eq!(
264 checked_arbitrary_take_rest::<&[u8]>(Unstructured::new(&x)).unwrap(),
265 &[1, 2, 3, 4]
266 );
267 assert_eq!(
268 checked_arbitrary_take_rest::<Vec<u8>>(Unstructured::new(&x)).unwrap(),
269 &[2, 4]
270 );
271 assert_eq!(
272 &*checked_arbitrary_take_rest::<Box<[u8]>>(Unstructured::new(&x)).unwrap(),
273 &[2, 4]
274 );
275 assert_eq!(
276 &*checked_arbitrary_take_rest::<Arc<[u8]>>(Unstructured::new(&x)).unwrap(),
277 &[2, 4]
278 );
279 assert_eq!(
280 &*checked_arbitrary_take_rest::<Rc<[u8]>>(Unstructured::new(&x)).unwrap(),
281 &[2, 4]
282 );
283 assert_eq!(
284 checked_arbitrary_take_rest::<Vec<u32>>(Unstructured::new(&x)).unwrap(),
285 &[0x040302]
286 );
287 assert_eq!(
288 checked_arbitrary_take_rest::<String>(Unstructured::new(&x)).unwrap(),
289 "\x01\x02\x03\x04"
290 );
291
292 // Empty remainder
293 assert_eq!(
294 checked_arbitrary_take_rest::<&[u8]>(Unstructured::new(&[])).unwrap(),
295 &[]
296 );
297 assert_eq!(
298 checked_arbitrary_take_rest::<Vec<u8>>(Unstructured::new(&[])).unwrap(),
299 &[]
300 );
301
302 // Cannot consume all but can consume part of the input
303 assert_eq!(
304 checked_arbitrary_take_rest::<String>(Unstructured::new(&[1, 0xFF, 2])).unwrap(),
305 "\x01"
306 );
307 }
308
309 #[test]
size_hint_for_tuples()310 fn size_hint_for_tuples() {
311 assert_eq!(
312 (7, Some(7)),
313 <(bool, u16, i32) as Arbitrary<'_>>::size_hint(0)
314 );
315 assert_eq!((1, None), <(u8, Vec<u8>) as Arbitrary>::size_hint(0));
316 }
317