1pub use quickcheck::{Arbitrary, Gen, TestResult, Testable};
85use std::{marker::PhantomData, ops::Range};
86
87pub use rand;
88use rand::{
89 distributions::uniform::SampleUniform, prelude::Distribution, seq::SliceRandom, Rng,
90 SeedableRng,
91};
92
93pub mod recursive;
94
95pub struct Random {
103 pub rng: rand::rngs::SmallRng,
104}
105
106impl Random {
107 pub fn arbitrary<T: Arbitrary>(&self) -> T {
108 let mut qcg = Gen::new(100);
109
110 Arbitrary::arbitrary(&mut qcg)
111 }
112
113 pub fn new() -> Self {
115 Random {
116 rng: rand::rngs::SmallRng::from_entropy(),
117 }
118 }
119
120 pub fn from_seed(seed: u64) -> Self {
121 let seed: Vec<u8> = seed
122 .to_be_bytes()
123 .into_iter()
124 .chain(std::iter::repeat(0))
125 .take(32)
126 .collect();
127 Random {
128 rng: rand::rngs::SmallRng::from_seed(seed[0..32].try_into().unwrap()),
129 }
130 }
131
132 pub fn choose<'a, T>(&mut self, slice: &'a [T]) -> Option<&'a T> {
136 slice.choose(&mut self.rng)
137 }
138
139 pub fn gen<T>(&mut self) -> T
140 where
141 rand::distributions::Standard: rand::distributions::Distribution<T>,
142 {
143 self.rng.gen()
144 }
145
146 pub fn gen_range<T, R>(&mut self, range: R) -> T
147 where
148 T: rand::distributions::uniform::SampleUniform,
149 R: rand::distributions::uniform::SampleRange<T>,
150 {
151 self.rng.gen_range(range)
152 }
153}
154
155pub type Shrunk<'a, T> = Box<dyn Iterator<Item = T> + 'a>;
157
158pub trait Sample {
160 type Output;
161
162 fn generate(&mut self, g: &mut Random) -> Self::Output;
164
165 fn shrink(&self, _: Self::Output) -> Shrunk<'_, Self::Output> {
168 Box::new(std::iter::empty())
169 }
170
171 fn try_convert<T, I, F>(self, from: F, try_into: I) -> TryConvert<Self, F, I>
201 where
202 Self: Sized,
203 F: Fn(Self::Output) -> T,
204 I: Fn(T) -> Option<Self::Output>,
205 {
206 TryConvert {
207 inner: self,
208 from,
209 try_into,
210 }
211 }
212
213 fn zip<OS>(self, other: OS) -> Zip<Self, OS>
215 where
216 Self: Sized,
217 OS: Sample,
218 {
219 Zip { t: (self, other) }
220 }
221
222 fn chain_resample<F, RS>(self, transform: F, subsamples: usize) -> ChainResample<Self, F>
236 where
237 Self: Sized,
238 F: Fn(Self::Output) -> RS,
239 RS: Sample,
240 {
241 ChainResample {
242 supersampler: self,
243 transform,
244 subsamples,
245 }
246 }
247}
248
249#[derive(Clone)]
251pub struct TryConvert<P, F, I> {
252 pub inner: P,
253 from: F,
254 try_into: I,
255}
256
257impl<P, F, I, T> Sample for TryConvert<P, F, I>
258where
259 P: Sample,
260 F: Fn(P::Output) -> T,
261 I: Fn(T) -> Option<P::Output>,
262{
263 type Output = T;
264
265 fn generate(&mut self, g: &mut Random) -> Self::Output {
266 (self.from)(P::generate(&mut self.inner, g))
267 }
268
269 fn shrink(&self, v: Self::Output) -> Shrunk<Self::Output> {
270 Box::new(
271 (self.try_into)(v)
272 .into_iter()
273 .flat_map(|v| P::shrink(&self.inner, v))
274 .map(&self.from),
275 )
276 }
277}
278
279#[derive(Clone)]
281pub struct Zip<A, B> {
282 t: (A, B),
283}
284
285impl<A, B> Sample for Zip<A, B>
286where
287 A: Sample,
288 B: Sample,
289 A::Output: Clone,
290 B::Output: Clone,
291{
292 type Output = (A::Output, B::Output);
293
294 fn generate(&mut self, g: &mut Random) -> Self::Output {
295 self.t.generate(g)
296 }
297
298 fn shrink(&self, v: Self::Output) -> Shrunk<Self::Output> {
299 self.t.shrink(v)
300 }
301}
302
303macro_rules! replace_expr {
304 ($_t:tt $sub:expr) => {
305 $sub
306 };
307}
308
309macro_rules! none_pad {
310 (($cur:ident) $($post: ident)*) => {
311 (Some($cur), $(replace_expr!($post None)),*)
312 };
313 ($($pre:ident)+ ($cur:ident) $($post: ident)*) => {
314 ($(replace_expr!($pre None)),*, Some($cur), $(replace_expr!($post None)),*)
315 };
316}
317
318macro_rules! shrink_tuple {
319 ($v:ident () $($sample: ident)*) => {
320 let ($(casey::lower!($sample)),*) = $v.clone();
321 let r = std::iter::empty();
322 shrink_tuple!(r $v () ($($sample)*));
323 };
324 ($r:ident $v:ident () ($cur:ident $($sample: ident)*)) => {
325 let (casey::lower!(ref $cur), $(casey::lower!(ref $sample)),*) = $v;
326 let r = $r.chain(
327 $cur.shrink(casey::lower!($cur).clone()).map(move |$cur| {
328 none_pad!(($cur) $($sample)*)
329 })
330 );
331 shrink_tuple!(r $v ($cur) ($($sample)*));
332 };
333 ($r:ident $v:ident ($($pre:ident)+) ($cur:ident $($sample: ident)*)) => {
334 let ($(casey::lower!(ref $pre)),*, casey::lower!(ref $cur), $(casey::lower!(ref $sample)),*) = $v;
335 let r = $r.chain(
336 $cur.shrink(casey::lower!($cur).clone()).map(move |$cur| {
337 none_pad!($($pre)* ($cur) $($sample)*)
338 })
339 );
340 shrink_tuple!(r $v ($($pre)* $cur) ($($sample)*));
341 };
342 ($r:ident $v:ident ($($pre:ident)*) ()) => {
343 let ($(casey::lower!($pre)),*) = $v;
344 return Box::new($r.map(move |($($pre),*)| {
345 ($($pre.unwrap_or(casey::lower!($pre).clone())),*)
346 }))
347 };
348}
349
350macro_rules! sample_tuple {
351 ($($name: ident),*) => {
352
353impl<$($name),*> Sample for ($($name),*,)
354where
355 $($name: Sample),*,
356 $($name::Output: Clone),*,
357{
358 type Output = ($($name::Output),*,);
359
360 #[allow(non_snake_case)]
361 fn generate(&mut self, r: &mut Random) -> Self::Output {
362 let ($(casey::lower!($name)),*,) = self;
363 ($(casey::lower!($name).generate(r)),*,)
364 }
365
366 #[allow(non_snake_case)]
367 fn shrink(&self, v: Self::Output) -> Shrunk<Self::Output> {
368 let ($($name),*,) = self;
369 shrink_tuple!(v () $($name)*);
370 }
371}
372
373 }
374}
375
376impl<A> Sample for (A,)
377where
378 A: Sample,
379{
380 type Output = (A::Output,);
381
382 fn generate(&mut self, g: &mut Random) -> Self::Output {
383 (self.0.generate(g),)
384 }
385
386 fn shrink(&self, v: Self::Output) -> Shrunk<Self::Output> {
387 Box::new(self.0.shrink(v.0).map(|v| (v,)))
388 }
389}
390
391sample_tuple!(A, B);
392sample_tuple!(A, B, C);
393sample_tuple!(A, B, C, D);
394sample_tuple!(A, B, C, D, E);
395sample_tuple!(A, B, C, D, E, F);
396sample_tuple!(A, B, C, D, E, F, G);
397sample_tuple!(A, B, C, D, E, F, G, H);
398
399#[derive(Clone, Debug)]
401pub struct ChainResample<S, F> {
402 supersampler: S,
403 transform: F,
404 subsamples: usize,
405}
406
407#[derive(Clone, Debug)]
409pub struct Chained<S, V> {
410 seed: S,
411 pub value: V,
412}
413
414impl<S, F, SS> Sample for ChainResample<S, F>
415where
416 S: Sample,
417 S::Output: Clone,
418 SS: Sample + 'static,
419 F: Fn(S::Output) -> SS,
420{
421 type Output = Chained<S::Output, SS::Output>;
422
423 fn generate(&mut self, g: &mut Random) -> Self::Output {
424 let seed = self.supersampler.generate(g);
425 let value = (self.transform)(seed.clone()).generate(g);
426
427 Chained { seed, value }
428 }
429
430 fn shrink(&self, v: Self::Output) -> Shrunk<Self::Output> {
431 Box::new(self.supersampler.shrink(v.seed).flat_map(|shrunk_seed| {
432 let mut g = Random::new();
433 let mut sampler = (self.transform)(shrunk_seed.clone());
434 (0..self.subsamples).map(move |_| Chained {
435 seed: shrunk_seed.clone(),
436 value: sampler.generate(&mut g),
437 })
438 }))
439 }
440}
441
442impl<T> Sample for Box<dyn Sample<Output = T>> {
443 type Output = T;
444
445 fn generate(&mut self, g: &mut Random) -> Self::Output {
446 self.as_mut().generate(g)
447 }
448
449 fn shrink(&self, v: Self::Output) -> Shrunk<'_, Self::Output> {
450 self.as_ref().shrink(v)
451 }
452}
453
454impl<T> Sample for Box<dyn Sample<Output = T> + Send + Sync> {
455 type Output = T;
456
457 fn generate(&mut self, g: &mut Random) -> Self::Output {
458 self.as_mut().generate(g)
459 }
460
461 fn shrink(&self, v: Self::Output) -> Shrunk<'_, Self::Output> {
462 self.as_ref().shrink(v)
463 }
464}
465
466#[derive(Debug, Clone)]
469pub struct Chance(pub f32);
470
471impl Sample for Chance {
472 type Output = bool;
473
474 fn generate(&mut self, g: &mut Random) -> Self::Output {
475 g.gen_range(0.0..1.0) < self.0
476 }
477}
478
479pub struct ArbitrarySampler<T> {
481 gen: Gen,
482 phantom: PhantomData<T>,
483 validate: fn(&T) -> bool,
484}
485
486impl<T> Clone for ArbitrarySampler<T> {
487 fn clone(&self) -> Self {
488 ArbitrarySampler {
489 gen: Gen::new(self.gen.size()),
490 phantom: self.phantom.clone(),
491 validate: self.validate.clone(),
492 }
493 }
494}
495
496impl<T: Arbitrary> Sample for ArbitrarySampler<T> {
497 type Output = T;
498
499 fn generate(&mut self, _: &mut Random) -> Self::Output {
500 for _ in 0..1000 {
501 let value = Arbitrary::arbitrary(&mut self.gen);
502 if (self.validate)(&value) {
503 return value;
504 }
505 }
506 panic!("could not find valid value after 1000 iterations")
507 }
508
509 fn shrink(&self, v: Self::Output) -> Shrunk<'_, Self::Output> {
510 Arbitrary::shrink(&v)
511 }
512}
513
514pub fn arbitrary<T: Arbitrary>() -> ArbitrarySampler<T> {
516 ArbitrarySampler {
517 gen: Gen::new(100),
518 phantom: PhantomData,
519 validate: |_| true,
520 }
521}
522
523pub fn valid_f32() -> ArbitrarySampler<f32> {
525 ArbitrarySampler {
526 gen: Gen::new(100),
527 phantom: PhantomData,
528 validate: |f| !f.is_nan(),
529 }
530}
531
532pub fn valid_f64() -> ArbitrarySampler<f64> {
534 ArbitrarySampler {
535 gen: Gen::new(100),
536 phantom: PhantomData,
537 validate: |f| !f.is_nan(),
538 }
539}
540
541#[derive(Debug, Clone)]
543pub struct Always<T>(pub T);
544
545impl<T: Clone> Sample for Always<T> {
546 type Output = T;
547
548 fn generate(&mut self, _: &mut Random) -> Self::Output {
549 self.0.clone()
550 }
551}
552
553pub fn choice<T, II>(choices: II) -> Choice<T>
568where
569 T: Clone + PartialEq,
570 II: IntoIterator<Item = T>,
571{
572 Choice {
573 choices: choices.into_iter().collect(),
574 }
575}
576
577#[derive(Clone, Debug)]
579pub struct Choice<T> {
580 pub choices: Vec<T>,
581}
582
583impl<T> Sample for Choice<T>
584where
585 T: Clone + PartialEq,
586{
587 type Output = T;
588
589 fn generate(&mut self, g: &mut Random) -> Self::Output {
590 g.choose(&self.choices).unwrap().clone()
591 }
592
593 fn shrink(&self, v: Self::Output) -> Shrunk<'_, Self::Output> {
594 let ix = self.choices.iter().position(|el| el == &v).unwrap_or(0);
595 Box::new((0..ix).map(|shrunk_ix| self.choices[shrunk_ix].clone()))
596 }
597}
598
599pub fn sampler_choice<C, II>(choices: II) -> SamplerChoice<C>
633where
634 II: IntoIterator<Item = C>,
635 C: Sample,
636 <C as Sample>::Output: Clone,
637{
638 SamplerChoice {
639 choices: choices.into_iter().collect(),
640 }
641}
642
643#[derive(Clone, Debug)]
645pub struct SamplerChoice<C> {
646 pub choices: Vec<C>,
647}
648
649impl<C> SamplerChoice<C> {
650 pub fn or(self, other: Self) -> Self {
651 Self {
652 choices: self
653 .choices
654 .into_iter()
655 .chain(other.choices.into_iter())
656 .collect(),
657 }
658 }
659}
660
661impl<C, T> Sample for SamplerChoice<C>
662where
663 C: Sample<Output = T>,
664 T: Clone + 'static,
665{
666 type Output = T;
667
668 fn generate(&mut self, g: &mut Random) -> Self::Output {
669 let ix = g.gen_range(0..self.choices.len());
670 self.choices[ix].generate(g)
671 }
672
673 fn shrink(&self, v: Self::Output) -> Shrunk<'_, Self::Output> {
674 Box::new(self.choices.iter().flat_map(move |c| c.shrink(v.clone())))
675 }
676}
677
678impl<T, I> Sample for Range<T>
679where
680 T: SampleUniform + Clone + PartialOrd + 'static,
681 Range<T>: IntoIterator<IntoIter = I>,
682 I: DoubleEndedIterator<Item = T> + 'static,
683{
684 type Output = T;
685
686 fn generate(&mut self, g: &mut Random) -> Self::Output {
687 g.gen_range(self.clone())
688 }
689
690 fn shrink(&self, v: Self::Output) -> Shrunk<'_, Self::Output> {
691 if self.start != v {
692 Box::new(
693 std::iter::once(self.start.clone())
694 .chain((self.start.clone()..v.clone()).into_iter().rev().take(1)),
695 )
696 } else {
697 Box::new(std::iter::empty())
698 }
699 }
700}
701
702#[derive(Clone, Debug)]
707pub struct Regex {
708 pub dist: rand_regex::Regex,
709 pub re: regex::Regex,
710}
711
712impl Regex {
713 pub fn new(pattern: &str) -> Self {
715 Regex {
716 dist: rand_regex::Regex::compile(pattern, 100).unwrap(),
717 re: regex::Regex::new(pattern).unwrap(),
718 }
719 }
720}
721
722impl Sample for Regex {
723 type Output = String;
724
725 fn generate(&mut self, g: &mut Random) -> Self::Output {
726 self.dist.sample(&mut g.rng)
727 }
728
729 fn shrink(&self, v: Self::Output) -> Shrunk<'_, Self::Output> {
730 let re = self.re.clone();
731 Box::new(Iterator::flat_map(0..v.len(), move |ix| {
735 let mut shrunk: String = String::with_capacity(v.len());
736 shrunk.push_str(&v[0..ix]);
737 shrunk.push_str(&v[ix..]);
738
739 if re.is_match(&shrunk) {
740 Some(shrunk)
741 } else {
742 None
743 }
744 }))
745 }
746}
747
748#[derive(Debug, Clone)]
754pub struct VecSampler<S, I> {
755 pub length: S,
756 pub el: I,
757}
758
759impl<S, I, T> Sample for VecSampler<S, I>
760where
761 S: Sample<Output = usize>,
762 I: Sample<Output = T>,
763 T: Clone + 'static,
764{
765 type Output = Vec<T>;
766
767 fn generate(&mut self, g: &mut Random) -> Self::Output {
768 Iterator::map(0..self.length.generate(g), |_| self.el.generate(g)).collect()
769 }
770
771 fn shrink(&self, v: Self::Output) -> Shrunk<'_, Self::Output> {
772 Box::new(self.length.shrink(v.len()).flat_map(move |new_len| {
773 assert!(new_len < v.len());
774 let gap = v.len() - new_len;
775
776 let iv = v.clone();
777 let iv2 = v.clone();
778
779 Iterator::map(0..new_len, move |cut| {
780 iv[0..cut]
781 .iter()
782 .chain(iv[cut + gap..].iter())
783 .cloned()
784 .collect()
785 })
786 .chain(Iterator::flat_map(0..v.len(), move |ix| {
787 let vref = iv2.clone();
788 let el = vref[ix].clone();
789 self.el.shrink(el).map(move |shrunk| {
790 let mut copy: Vec<T> = vref.clone();
791 copy[ix] = shrunk.clone();
792 copy.clone()
793 })
794 }))
795 }))
796 }
797}
798
799pub fn sample_all<S>(samplers: Vec<S>) -> SampleAll<S>
805where
806 S: Sample,
807{
808 SampleAll { samplers }
809}
810
811pub struct SampleAll<S> {
813 pub samplers: Vec<S>,
814}
815
816impl<S> Sample for SampleAll<S>
817where
818 S: Sample,
819 S::Output: Clone,
820{
821 type Output = Vec<S::Output>;
822
823 fn generate(&mut self, g: &mut Random) -> Self::Output {
824 self.samplers.iter_mut().map(|s| s.generate(g)).collect()
825 }
826
827 fn shrink(&self, v: Self::Output) -> Shrunk<'_, Self::Output> {
828 Box::new((0..self.samplers.len()).flat_map(move |ix| {
829 let mut updated = v.clone();
830
831 self.samplers[ix]
832 .shrink(updated[ix].clone())
833 .map(move |sv| {
834 updated[ix] = sv;
835 updated.clone()
836 })
837 }))
838 }
839}
840
841#[cfg(test)]
842mod tests {}