1use crate::{
2 driver, input::SliceDebug, panic, panic::PanicError, Failure, Input, IntoResult, Seed,
3 ValueGenerator,
4};
5use std::panic::RefUnwindSafe;
6
7pub trait Test: Sized {
9 type Value;
11
12 fn test<T: Input<Result<bool, PanicError>>>(
14 &mut self,
15 input: &mut T,
16 ) -> Result<bool, PanicError>;
17
18 fn generate_value<T: Input<Self::Value>>(&self, input: &mut T) -> Self::Value;
22
23 fn shrink<I: crate::shrink::Input>(
25 &mut self,
26 input: I,
27 seed: Option<Seed>,
28 options: &driver::Options,
29 ) -> Option<Failure<Self::Value>> {
30 crate::shrink::shrink(self, input, seed, options)
31 }
32}
33
34impl<F: RefUnwindSafe + FnMut(&[u8]) -> Ret, Ret> Test for F
35where
36 Ret: IntoResult,
37{
38 type Value = SliceDebug<Vec<u8>>;
39
40 #[inline]
41 fn test<T: Input<Result<bool, PanicError>>>(
42 &mut self,
43 input: &mut T,
44 ) -> Result<bool, PanicError> {
45 input.with_slice(&mut |slice| {
46 panic::catch(|| {
47 let res = (self)(slice);
48 match res.into_result() {
49 Ok(()) => Ok(true),
50 Err(err) => Err(err),
51 }
52 })
53 })
54 }
55
56 #[inline]
57 fn generate_value<T: Input<Self::Value>>(&self, input: &mut T) -> Self::Value {
58 input.with_slice(&mut |slice| SliceDebug(slice.to_vec()))
59 }
60}
61
62pub struct BorrowedSliceTest<F> {
63 fun: F,
64}
65
66impl<F> BorrowedSliceTest<F> {
67 pub fn new(fun: F) -> Self {
68 Self { fun }
69 }
70}
71
72impl<F: RefUnwindSafe + FnMut(&[u8]) -> Ret, Ret> Test for BorrowedSliceTest<F>
73where
74 Ret: IntoResult,
75{
76 type Value = SliceDebug<Vec<u8>>;
77
78 #[inline]
79 fn test<T: Input<Result<bool, PanicError>>>(
80 &mut self,
81 input: &mut T,
82 ) -> Result<bool, PanicError> {
83 input.with_slice(&mut |slice| {
84 panic::catch(|| {
85 let res = (self.fun)(slice);
86 match res.into_result() {
87 Ok(()) => Ok(true),
88 Err(err) => Err(err),
89 }
90 })
91 })
92 }
93
94 #[inline]
95 fn generate_value<T: Input<Self::Value>>(&self, input: &mut T) -> Self::Value {
96 input.with_slice(&mut |slice| SliceDebug(slice.to_vec()))
97 }
98}
99
100pub struct ClonedSliceTest<F> {
101 fun: F,
102}
103
104impl<F> ClonedSliceTest<F> {
105 pub fn new(fun: F) -> Self {
106 Self { fun }
107 }
108}
109
110impl<F: RefUnwindSafe + FnMut(Vec<u8>) -> Ret, Ret> Test for ClonedSliceTest<F>
111where
112 Ret: IntoResult,
113{
114 type Value = SliceDebug<Vec<u8>>;
115
116 #[inline]
117 fn test<T: Input<Result<bool, PanicError>>>(
118 &mut self,
119 input: &mut T,
120 ) -> Result<bool, PanicError> {
121 input.with_slice(&mut |slice| {
122 panic::catch(|| {
123 let input = slice.to_vec();
124 let res = (self.fun)(input);
125 match res.into_result() {
126 Ok(()) => Ok(true),
127 Err(err) => Err(err),
128 }
129 })
130 })
131 }
132
133 #[inline]
134 fn generate_value<T: Input<Self::Value>>(&self, input: &mut T) -> Self::Value {
135 input.with_slice(&mut |slice| SliceDebug(slice.to_vec()))
136 }
137}
138
139#[cfg(not(kani))]
141macro_rules! generate_value {
142 ($self:ident, $driver:ident) => {{
143 let forward_panic = crate::panic::forward_panic(true);
144 let value = if let Some(value) = $self.value.as_mut() {
145 if $self.produce.mutate($driver, value).is_some() {
146 value
147 } else {
148 crate::panic::forward_panic(forward_panic);
149 return Ok(false);
150 }
151 } else if let Some(value) = $self.produce.generate($driver) {
152 $self.value = Some(value);
153 $self.value.as_ref().unwrap()
154 } else {
155 crate::panic::forward_panic(forward_panic);
156 return Ok(false);
157 };
158 crate::panic::forward_panic(forward_panic);
159 value
160 }};
161}
162#[cfg(kani)]
163macro_rules! generate_value {
164 ($self:ident, $driver:ident) => {{
165 $self.value = $self.produce.generate($driver);
166 kani::assume($self.value.is_some());
167 $self.value.as_ref().unwrap()
168 }};
169}
170
171pub struct BorrowedGeneratorTest<F, G, V> {
172 fun: F,
173 produce: G,
174 value: Option<V>,
175}
176
177impl<F, G, V> BorrowedGeneratorTest<F, G, V> {
178 pub fn new(fun: F, produce: G) -> Self {
179 Self {
180 fun,
181 produce,
182 value: None,
183 }
184 }
185}
186
187impl<F: RefUnwindSafe + FnMut(&G::Output) -> Ret, G: ValueGenerator, Ret> Test
188 for BorrowedGeneratorTest<F, G, G::Output>
189where
190 Ret: IntoResult,
191 G::Output: core::fmt::Debug,
192{
193 type Value = G::Output;
194
195 #[inline]
196 fn test<T: Input<Result<bool, PanicError>>>(
197 &mut self,
198 input: &mut T,
199 ) -> Result<bool, PanicError> {
200 input.with_driver(&mut |driver| {
201 let fun = &mut self.fun;
202
203 let value = core::panic::AssertUnwindSafe(generate_value!(self, driver));
205
206 panic::catch(|| {
207 let res = (fun)(&value);
208 match res.into_result() {
209 Ok(()) => Ok(true),
210 Err(err) => Err(err),
211 }
212 })
213 })
214 }
215
216 #[inline]
217 fn generate_value<T: Input<Self::Value>>(&self, input: &mut T) -> Self::Value {
218 input.with_driver(&mut |driver| {
219 let forward_panic = crate::panic::forward_panic(true);
220 let value = self.produce.generate(driver).unwrap();
221 crate::panic::forward_panic(forward_panic);
222 value
223 })
224 }
225}
226
227pub struct ClonedGeneratorTest<F, G, V> {
228 fun: F,
229 produce: G,
230 value: Option<V>,
231}
232
233impl<F, G, V> ClonedGeneratorTest<F, G, V> {
234 pub fn new(fun: F, produce: G) -> Self {
235 Self {
236 fun,
237 produce,
238 value: None,
239 }
240 }
241}
242
243impl<F: RefUnwindSafe + FnMut(G::Output) -> Ret, G: ValueGenerator, Ret> Test
244 for ClonedGeneratorTest<F, G, G::Output>
245where
246 Ret: IntoResult,
247 G::Output: core::fmt::Debug + Clone + RefUnwindSafe,
248{
249 type Value = G::Output;
250
251 #[inline]
252 fn test<T: Input<Result<bool, PanicError>>>(
253 &mut self,
254 input: &mut T,
255 ) -> Result<bool, PanicError> {
256 input.with_driver(&mut |driver| {
257 let fun = &mut self.fun;
258
259 let value = generate_value!(self, driver);
260
261 #[cfg(kani)]
262 let input = {
263 let _ = value;
264 self.value.take().unwrap()
265 };
266
267 #[cfg(not(kani))]
268 let input = value.clone();
269
270 let input = core::panic::AssertUnwindSafe(input);
272
273 panic::catch(move || {
274 let core::panic::AssertUnwindSafe(input) = input;
275 let res = (fun)(input);
276 match res.into_result() {
277 Ok(()) => Ok(true),
278 Err(err) => Err(err),
279 }
280 })
281 })
282 }
283
284 #[inline]
285 fn generate_value<T: Input<Self::Value>>(&self, input: &mut T) -> Self::Value {
286 input.with_driver(&mut |driver| {
287 let forward_panic = crate::panic::forward_panic(true);
288 let value = self.produce.generate(driver).unwrap();
289 crate::panic::forward_panic(forward_panic);
290 value
291 })
292 }
293}