1use core::cmp::Ord;
13use core::hash::Hash;
14use core::ops::{Add, Range, RangeInclusive, RangeTo, RangeToInclusive};
15use core::usize;
16
17use crate::std_facade::{
18 fmt, BTreeMap, BTreeSet, BinaryHeap, LinkedList, Vec, VecDeque,
19};
20
21#[cfg(feature = "std")]
22use crate::std_facade::{HashMap, HashSet};
23
24use crate::bits::{BitSetLike, VarBitSet};
25use crate::num::sample_uniform_incl;
26use crate::strategy::*;
27use crate::test_runner::*;
28use crate::tuple::TupleValueTree;
29
30#[derive(Clone, PartialEq, Eq, Hash, Debug)]
42pub struct SizeRange(Range<usize>);
43
44pub fn size_range(from: impl Into<SizeRange>) -> SizeRange {
46 from.into()
47}
48
49impl Default for SizeRange {
50 fn default() -> Self {
52 size_range(0..100)
53 }
54}
55
56impl SizeRange {
57 pub fn new(range: RangeInclusive<usize>) -> Self {
59 range.into()
60 }
61
62 pub fn with<X>(self, and: X) -> product_type![Self, X] {
69 product_pack![self, and]
70 }
71
72 pub fn lift<X: Default>(self) -> product_type![Self, X] {
77 self.with(Default::default())
78 }
79
80 pub(crate) fn start(&self) -> usize {
81 self.0.start
82 }
83
84 pub(crate) fn start_end_incl(&self) -> (usize, usize) {
86 (self.start(), self.end_incl())
87 }
88
89 pub(crate) fn end_incl(&self) -> usize {
90 self.0.end - 1
91 }
92
93 pub(crate) fn end_excl(&self) -> usize {
94 self.0.end
95 }
96
97 pub(crate) fn iter(&self) -> impl Iterator<Item = usize> {
98 self.0.clone().into_iter()
99 }
100
101 pub(crate) fn is_empty(&self) -> bool {
102 self.start() == self.end_excl()
103 }
104
105 pub(crate) fn assert_nonempty(&self) {
106 if self.is_empty() {
107 panic!(
108 "Invalid use of empty size range. (hint: did you \
109 accidentally write {}..{} where you meant {}..={} \
110 somewhere?)",
111 self.start(),
112 self.end_excl(),
113 self.start(),
114 self.end_excl()
115 );
116 }
117 }
118}
119
120impl From<(usize, usize)> for SizeRange {
123 fn from((low, high): (usize, usize)) -> Self {
124 size_range(low..high)
125 }
126}
127
128impl From<usize> for SizeRange {
130 fn from(exact: usize) -> Self {
131 size_range(exact..=exact)
132 }
133}
134
135impl From<RangeTo<usize>> for SizeRange {
137 fn from(high: RangeTo<usize>) -> Self {
138 size_range(0..high.end)
139 }
140}
141
142impl From<Range<usize>> for SizeRange {
144 fn from(r: Range<usize>) -> Self {
145 SizeRange(r)
146 }
147}
148
149impl From<RangeInclusive<usize>> for SizeRange {
151 fn from(r: RangeInclusive<usize>) -> Self {
152 size_range(*r.start()..r.end().saturating_add(1))
153 }
154}
155
156impl From<RangeToInclusive<usize>> for SizeRange {
158 fn from(high: RangeToInclusive<usize>) -> Self {
159 size_range(0..=high.end)
160 }
161}
162
163#[cfg(feature = "frunk")]
164impl Generic for SizeRange {
165 type Repr = RangeInclusive<usize>;
166
167 fn into(self) -> Self::Repr {
169 self.0
170 }
171
172 fn from(r: Self::Repr) -> Self {
174 r.into()
175 }
176}
177
178impl Add<usize> for SizeRange {
182 type Output = SizeRange;
183
184 fn add(self, rhs: usize) -> Self::Output {
185 let (start, end) = self.start_end_incl();
186 size_range((start + rhs)..=(end + rhs))
187 }
188}
189
190#[must_use = "strategies do nothing unless used"]
198#[derive(Clone, Debug)]
199pub struct VecStrategy<T: Strategy> {
200 element: T,
201 size: SizeRange,
202}
203
204pub fn vec<T: Strategy>(
210 element: T,
211 size: impl Into<SizeRange>,
212) -> VecStrategy<T> {
213 let size = size.into();
214 size.assert_nonempty();
215 VecStrategy { element, size }
216}
217
218mapfn! {
219 [] fn VecToDeque[<T : fmt::Debug>](vec: Vec<T>) -> VecDeque<T> {
220 vec.into()
221 }
222}
223
224opaque_strategy_wrapper! {
225 #[derive(Clone, Debug)]
229 pub struct VecDequeStrategy[<T>][where T : Strategy](
230 statics::Map<VecStrategy<T>, VecToDeque>)
231 -> VecDequeValueTree<T::Tree>;
232 #[derive(Clone, Debug)]
234 pub struct VecDequeValueTree[<T>][where T : ValueTree](
235 statics::Map<VecValueTree<T>, VecToDeque>)
236 -> VecDeque<T::Value>;
237}
238
239pub fn vec_deque<T: Strategy>(
242 element: T,
243 size: impl Into<SizeRange>,
244) -> VecDequeStrategy<T> {
245 VecDequeStrategy(statics::Map::new(vec(element, size), VecToDeque))
246}
247
248mapfn! {
249 [] fn VecToLl[<T : fmt::Debug>](vec: Vec<T>) -> LinkedList<T> {
250 vec.into_iter().collect()
251 }
252}
253
254opaque_strategy_wrapper! {
255 #[derive(Clone, Debug)]
259 pub struct LinkedListStrategy[<T>][where T : Strategy](
260 statics::Map<VecStrategy<T>, VecToLl>)
261 -> LinkedListValueTree<T::Tree>;
262 #[derive(Clone, Debug)]
264 pub struct LinkedListValueTree[<T>][where T : ValueTree](
265 statics::Map<VecValueTree<T>, VecToLl>)
266 -> LinkedList<T::Value>;
267}
268
269pub fn linked_list<T: Strategy>(
272 element: T,
273 size: impl Into<SizeRange>,
274) -> LinkedListStrategy<T> {
275 LinkedListStrategy(statics::Map::new(vec(element, size), VecToLl))
276}
277
278mapfn! {
279 [] fn VecToBinHeap[<T : fmt::Debug + Ord>](vec: Vec<T>) -> BinaryHeap<T> {
280 vec.into()
281 }
282}
283
284opaque_strategy_wrapper! {
285 #[derive(Clone, Debug)]
289 pub struct BinaryHeapStrategy[<T>][where T : Strategy, T::Value : Ord](
290 statics::Map<VecStrategy<T>, VecToBinHeap>)
291 -> BinaryHeapValueTree<T::Tree>;
292 #[derive(Clone, Debug)]
294 pub struct BinaryHeapValueTree[<T>][where T : ValueTree, T::Value : Ord](
295 statics::Map<VecValueTree<T>, VecToBinHeap>)
296 -> BinaryHeap<T::Value>;
297}
298
299pub fn binary_heap<T: Strategy>(
302 element: T,
303 size: impl Into<SizeRange>,
304) -> BinaryHeapStrategy<T>
305where
306 T::Value: Ord,
307{
308 BinaryHeapStrategy(statics::Map::new(vec(element, size), VecToBinHeap))
309}
310
311mapfn! {
312 {#[cfg(feature = "std")]}
313 [] fn VecToHashSet[<T : fmt::Debug + Hash + Eq>](vec: Vec<T>)
314 -> HashSet<T> {
315 vec.into_iter().collect()
316 }
317}
318
319#[derive(Debug, Clone, Copy)]
320struct MinSize(usize);
321
322#[cfg(feature = "std")]
323impl<T: Eq + Hash> statics::FilterFn<HashSet<T>> for MinSize {
324 fn apply(&self, set: &HashSet<T>) -> bool {
325 set.len() >= self.0
326 }
327}
328
329opaque_strategy_wrapper! {
330 {#[cfg(feature = "std")]}
331 #[derive(Clone, Debug)]
335 pub struct HashSetStrategy[<T>][where T : Strategy, T::Value : Hash + Eq](
336 statics::Filter<statics::Map<VecStrategy<T>, VecToHashSet>, MinSize>)
337 -> HashSetValueTree<T::Tree>;
338 #[derive(Clone, Debug)]
340 pub struct HashSetValueTree[<T>][where T : ValueTree, T::Value : Hash + Eq](
341 statics::Filter<statics::Map<VecValueTree<T>, VecToHashSet>, MinSize>)
342 -> HashSet<T::Value>;
343}
344
345#[cfg(feature = "std")]
352pub fn hash_set<T: Strategy>(
353 element: T,
354 size: impl Into<SizeRange>,
355) -> HashSetStrategy<T>
356where
357 T::Value: Hash + Eq,
358{
359 let size = size.into();
360 HashSetStrategy(statics::Filter::new(
361 statics::Map::new(vec(element, size.clone()), VecToHashSet),
362 "HashSet minimum size".into(),
363 MinSize(size.start()),
364 ))
365}
366
367mapfn! {
368 [] fn VecToBTreeSet[<T : fmt::Debug + Ord>](vec: Vec<T>)
369 -> BTreeSet<T> {
370 vec.into_iter().collect()
371 }
372}
373
374impl<T: Ord> statics::FilterFn<BTreeSet<T>> for MinSize {
375 fn apply(&self, set: &BTreeSet<T>) -> bool {
376 set.len() >= self.0
377 }
378}
379
380opaque_strategy_wrapper! {
381 #[derive(Clone, Debug)]
385 pub struct BTreeSetStrategy[<T>][where T : Strategy, T::Value : Ord](
386 statics::Filter<statics::Map<VecStrategy<T>, VecToBTreeSet>, MinSize>)
387 -> BTreeSetValueTree<T::Tree>;
388 #[derive(Clone, Debug)]
390 pub struct BTreeSetValueTree[<T>][where T : ValueTree, T::Value : Ord](
391 statics::Filter<statics::Map<VecValueTree<T>, VecToBTreeSet>, MinSize>)
392 -> BTreeSet<T::Value>;
393}
394
395pub fn btree_set<T: Strategy>(
402 element: T,
403 size: impl Into<SizeRange>,
404) -> BTreeSetStrategy<T>
405where
406 T::Value: Ord,
407{
408 let size = size.into();
409 BTreeSetStrategy(statics::Filter::new(
410 statics::Map::new(vec(element, size.clone()), VecToBTreeSet),
411 "BTreeSet minimum size".into(),
412 MinSize(size.start()),
413 ))
414}
415
416mapfn! {
417 {#[cfg(feature = "std")]}
418 [] fn VecToHashMap[<K : fmt::Debug + Hash + Eq, V : fmt::Debug>]
419 (vec: Vec<(K, V)>) -> HashMap<K, V>
420 {
421 vec.into_iter().collect()
422 }
423}
424
425#[cfg(feature = "std")]
426impl<K: Hash + Eq, V> statics::FilterFn<HashMap<K, V>> for MinSize {
427 fn apply(&self, map: &HashMap<K, V>) -> bool {
428 map.len() >= self.0
429 }
430}
431
432opaque_strategy_wrapper! {
433 {#[cfg(feature = "std")]}
434 #[derive(Clone, Debug)]
438 pub struct HashMapStrategy[<K, V>]
439 [where K : Strategy, V : Strategy, K::Value : Hash + Eq](
440 statics::Filter<statics::Map<VecStrategy<(K,V)>,
441 VecToHashMap>, MinSize>)
442 -> HashMapValueTree<K::Tree, V::Tree>;
443 #[derive(Clone, Debug)]
445 pub struct HashMapValueTree[<K, V>]
446 [where K : ValueTree, V : ValueTree, K::Value : Hash + Eq](
447 statics::Filter<statics::Map<VecValueTree<TupleValueTree<(K, V)>>,
448 VecToHashMap>, MinSize>)
449 -> HashMap<K::Value, V::Value>;
450}
451
452#[cfg(feature = "std")]
460pub fn hash_map<K: Strategy, V: Strategy>(
461 key: K,
462 value: V,
463 size: impl Into<SizeRange>,
464) -> HashMapStrategy<K, V>
465where
466 K::Value: Hash + Eq,
467{
468 let size = size.into();
469 HashMapStrategy(statics::Filter::new(
470 statics::Map::new(vec((key, value), size.clone()), VecToHashMap),
471 "HashMap minimum size".into(),
472 MinSize(size.start()),
473 ))
474}
475
476mapfn! {
477 [] fn VecToBTreeMap[<K : fmt::Debug + Ord, V : fmt::Debug>]
478 (vec: Vec<(K, V)>) -> BTreeMap<K, V>
479 {
480 vec.into_iter().collect()
481 }
482}
483
484impl<K: Ord, V> statics::FilterFn<BTreeMap<K, V>> for MinSize {
485 fn apply(&self, map: &BTreeMap<K, V>) -> bool {
486 map.len() >= self.0
487 }
488}
489
490opaque_strategy_wrapper! {
491 #[derive(Clone, Debug)]
495 pub struct BTreeMapStrategy[<K, V>]
496 [where K : Strategy, V : Strategy, K::Value : Ord](
497 statics::Filter<statics::Map<VecStrategy<(K,V)>,
498 VecToBTreeMap>, MinSize>)
499 -> BTreeMapValueTree<K::Tree, V::Tree>;
500 #[derive(Clone, Debug)]
502 pub struct BTreeMapValueTree[<K, V>]
503 [where K : ValueTree, V : ValueTree, K::Value : Ord](
504 statics::Filter<statics::Map<VecValueTree<TupleValueTree<(K, V)>>,
505 VecToBTreeMap>, MinSize>)
506 -> BTreeMap<K::Value, V::Value>;
507}
508
509pub fn btree_map<K: Strategy, V: Strategy>(
517 key: K,
518 value: V,
519 size: impl Into<SizeRange>,
520) -> BTreeMapStrategy<K, V>
521where
522 K::Value: Ord,
523{
524 let size = size.into();
525 BTreeMapStrategy(statics::Filter::new(
526 statics::Map::new(vec((key, value), size.clone()), VecToBTreeMap),
527 "BTreeMap minimum size".into(),
528 MinSize(size.start()),
529 ))
530}
531
532#[derive(Clone, Copy, Debug)]
533enum Shrink {
534 DeleteElement(usize),
535 ShrinkElement(usize),
536}
537
538#[derive(Clone, Debug)]
540pub struct VecValueTree<T: ValueTree> {
541 elements: Vec<T>,
542 included_elements: VarBitSet,
543 min_size: usize,
544 shrink: Shrink,
545 prev_shrink: Option<Shrink>,
546}
547
548impl<T: Strategy> Strategy for VecStrategy<T> {
549 type Tree = VecValueTree<T::Tree>;
550 type Value = Vec<T::Value>;
551
552 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
553 let (start, end) = self.size.start_end_incl();
554 let max_size = sample_uniform_incl(runner, start, end);
555 let mut elements = Vec::with_capacity(max_size);
556 while elements.len() < max_size {
557 elements.push(self.element.new_tree(runner)?);
558 }
559
560 Ok(VecValueTree {
561 elements,
562 included_elements: VarBitSet::saturated(max_size),
563 min_size: start,
564 shrink: Shrink::DeleteElement(0),
565 prev_shrink: None,
566 })
567 }
568}
569
570impl<T: Strategy> Strategy for Vec<T> {
571 type Tree = VecValueTree<T::Tree>;
572 type Value = Vec<T::Value>;
573
574 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
575 let len = self.len();
576 let elements = self
577 .iter()
578 .map(|t| t.new_tree(runner))
579 .collect::<Result<Vec<_>, Reason>>()?;
580
581 Ok(VecValueTree {
582 elements,
583 included_elements: VarBitSet::saturated(len),
584 min_size: len,
585 shrink: Shrink::ShrinkElement(0),
586 prev_shrink: None,
587 })
588 }
589}
590
591impl<T: ValueTree> ValueTree for VecValueTree<T> {
592 type Value = Vec<T::Value>;
593
594 fn current(&self) -> Vec<T::Value> {
595 self.elements
596 .iter()
597 .enumerate()
598 .filter(|&(ix, _)| self.included_elements.test(ix))
599 .map(|(_, element)| element.current())
600 .collect()
601 }
602
603 fn simplify(&mut self) -> bool {
604 if let Shrink::DeleteElement(ix) = self.shrink {
611 if ix >= self.elements.len()
614 || self.included_elements.count() == self.min_size
615 {
616 self.shrink = Shrink::ShrinkElement(0);
617 } else {
618 self.included_elements.clear(ix);
619 self.prev_shrink = Some(self.shrink);
620 self.shrink = Shrink::DeleteElement(ix + 1);
621 return true;
622 }
623 }
624
625 while let Shrink::ShrinkElement(ix) = self.shrink {
626 if ix >= self.elements.len() {
627 return false;
629 }
630
631 if !self.included_elements.test(ix) {
632 self.shrink = Shrink::ShrinkElement(ix + 1);
634 continue;
635 }
636
637 if !self.elements[ix].simplify() {
638 self.shrink = Shrink::ShrinkElement(ix + 1);
640 } else {
641 self.prev_shrink = Some(self.shrink);
642 return true;
643 }
644 }
645
646 panic!("Unexpected shrink state");
647 }
648
649 fn complicate(&mut self) -> bool {
650 match self.prev_shrink {
651 None => false,
652 Some(Shrink::DeleteElement(ix)) => {
653 self.included_elements.set(ix);
656 self.prev_shrink = None;
657 true
658 }
659 Some(Shrink::ShrinkElement(ix)) => {
660 if self.elements[ix].complicate() {
661 true
664 } else {
665 self.prev_shrink = None;
667 false
668 }
669 }
670 }
671 }
672}
673
674#[cfg(test)]
679mod test {
680 use super::*;
681
682 use crate::bits;
683
684 #[test]
685 fn test_vec() {
686 let input = vec(1usize..20usize, 5..20);
687 let mut num_successes = 0;
688
689 let mut runner = TestRunner::deterministic();
690 for _ in 0..256 {
691 let case = input.new_tree(&mut runner).unwrap();
692 let start = case.current();
693 assert!(start.len() >= 5 && start.len() < 20);
695 assert!(start.iter().map(|&v| v).collect::<VarBitSet>().len() >= 2);
697
698 let result = runner.run_one(case, |v| {
699 prop_assert!(
700 v.iter().map(|&v| v).sum::<usize>() < 9,
701 "greater than 8"
702 );
703 Ok(())
704 });
705
706 match result {
707 Ok(true) => num_successes += 1,
708 Err(TestError::Fail(_, value)) => {
709 assert!(
713 value.len() >= 5
714 && value.len() <= 9
715 && value.iter().map(|&v| v).sum::<usize>() == 9,
716 "Unexpected minimal value: {:?}",
717 value
718 );
719 }
720 e => panic!("Unexpected result: {:?}", e),
721 }
722 }
723
724 assert!(num_successes < 256);
725 }
726
727 #[test]
728 fn test_vec_sanity() {
729 check_strategy_sanity(vec(0i32..1000, 5..10), None);
730 }
731
732 #[test]
733 fn test_parallel_vec() {
734 let input =
735 vec![(1u32..10).boxed(), bits::u32::masked(0xF0u32).boxed()];
736
737 for _ in 0..256 {
738 let mut runner = TestRunner::default();
739 let mut case = input.new_tree(&mut runner).unwrap();
740
741 loop {
742 let current = case.current();
743 assert_eq!(2, current.len());
744 assert!(current[0] >= 1 && current[0] <= 10);
745 assert_eq!(0, (current[1] & !0xF0));
746
747 if !case.simplify() {
748 break;
749 }
750 }
751 }
752 }
753
754 #[cfg(feature = "std")]
755 #[test]
756 fn test_map() {
757 let input = hash_map("[ab]{3}", "a", 2..3);
759 let mut runner = TestRunner::deterministic();
760
761 for _ in 0..256 {
762 let v = input.new_tree(&mut runner).unwrap().current();
763 assert_eq!(2, v.len());
764 }
765 }
766
767 #[cfg(feature = "std")]
768 #[test]
769 fn test_set() {
770 let input = hash_set("[ab]{3}", 2..3);
772 let mut runner = TestRunner::deterministic();
773
774 for _ in 0..256 {
775 let v = input.new_tree(&mut runner).unwrap().current();
776 assert_eq!(2, v.len());
777 }
778 }
779}