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)]
43pub struct SizeRange(Range<usize>);
44
45pub fn size_range(from: impl Into<SizeRange>) -> SizeRange {
47 from.into()
48}
49
50impl Default for SizeRange {
51 fn default() -> Self {
54 size_range(0..Config::default().max_default_size_range)
55 }
56}
57
58impl SizeRange {
59 pub fn new(range: RangeInclusive<usize>) -> Self {
61 range.into()
62 }
63
64 pub fn with<X>(self, and: X) -> product_type![Self, X] {
71 product_pack![self, and]
72 }
73
74 pub fn lift<X: Default>(self) -> product_type![Self, X] {
79 self.with(Default::default())
80 }
81
82 pub fn start(&self) -> usize {
84 self.0.start
85 }
86
87 pub fn start_end_incl(&self) -> (usize, usize) {
89 (self.start(), self.end_incl())
90 }
91
92 pub fn end_incl(&self) -> usize {
94 self.0.end - 1
95 }
96
97 pub fn end_excl(&self) -> usize {
99 self.0.end
100 }
101
102 pub(crate) fn iter(&self) -> impl Iterator<Item = usize> {
103 self.0.clone().into_iter()
104 }
105
106 pub(crate) fn is_empty(&self) -> bool {
107 self.start() == self.end_excl()
108 }
109
110 pub(crate) fn assert_nonempty(&self) {
111 if self.is_empty() {
112 panic!(
113 "Invalid use of empty size range. (hint: did you \
114 accidentally write {}..{} where you meant {}..={} \
115 somewhere?)",
116 self.start(),
117 self.end_excl(),
118 self.start(),
119 self.end_excl()
120 );
121 }
122 }
123}
124
125impl From<(usize, usize)> for SizeRange {
128 fn from((low, high): (usize, usize)) -> Self {
129 size_range(low..high)
130 }
131}
132
133impl From<usize> for SizeRange {
135 fn from(exact: usize) -> Self {
136 size_range(exact..=exact)
137 }
138}
139
140impl From<RangeTo<usize>> for SizeRange {
142 fn from(high: RangeTo<usize>) -> Self {
143 size_range(0..high.end)
144 }
145}
146
147impl From<Range<usize>> for SizeRange {
149 fn from(r: Range<usize>) -> Self {
150 SizeRange(r)
151 }
152}
153
154impl From<RangeInclusive<usize>> for SizeRange {
156 fn from(r: RangeInclusive<usize>) -> Self {
157 size_range(*r.start()..r.end().saturating_add(1))
158 }
159}
160
161impl From<RangeToInclusive<usize>> for SizeRange {
163 fn from(high: RangeToInclusive<usize>) -> Self {
164 size_range(0..=high.end)
165 }
166}
167
168impl From<SizeRange> for Range<usize> {
169 fn from(size_range: SizeRange) -> Self {
170 size_range.0
171 }
172}
173
174impl Add<usize> for SizeRange {
178 type Output = SizeRange;
179
180 fn add(self, rhs: usize) -> Self::Output {
181 let (start, end) = self.start_end_incl();
182 size_range((start + rhs)..=(end + rhs))
183 }
184}
185
186#[must_use = "strategies do nothing unless used"]
194#[derive(Clone, Debug)]
195pub struct VecStrategy<T: Strategy> {
196 element: T,
197 size: SizeRange,
198}
199
200pub fn vec<T: Strategy>(
206 element: T,
207 size: impl Into<SizeRange>,
208) -> VecStrategy<T> {
209 let size = size.into();
210 size.assert_nonempty();
211 VecStrategy { element, size }
212}
213
214mapfn! {
215 [] fn VecToDeque[<T : fmt::Debug>](vec: Vec<T>) -> VecDeque<T> {
216 vec.into()
217 }
218}
219
220opaque_strategy_wrapper! {
221 #[derive(Clone, Debug)]
225 pub struct VecDequeStrategy[<T>][where T : Strategy](
226 statics::Map<VecStrategy<T>, VecToDeque>)
227 -> VecDequeValueTree<T::Tree>;
228 #[derive(Clone, Debug)]
230 pub struct VecDequeValueTree[<T>][where T : ValueTree](
231 statics::Map<VecValueTree<T>, VecToDeque>)
232 -> VecDeque<T::Value>;
233}
234
235pub fn vec_deque<T: Strategy>(
238 element: T,
239 size: impl Into<SizeRange>,
240) -> VecDequeStrategy<T> {
241 VecDequeStrategy(statics::Map::new(vec(element, size), VecToDeque))
242}
243
244mapfn! {
245 [] fn VecToLl[<T : fmt::Debug>](vec: Vec<T>) -> LinkedList<T> {
246 vec.into_iter().collect()
247 }
248}
249
250opaque_strategy_wrapper! {
251 #[derive(Clone, Debug)]
255 pub struct LinkedListStrategy[<T>][where T : Strategy](
256 statics::Map<VecStrategy<T>, VecToLl>)
257 -> LinkedListValueTree<T::Tree>;
258 #[derive(Clone, Debug)]
260 pub struct LinkedListValueTree[<T>][where T : ValueTree](
261 statics::Map<VecValueTree<T>, VecToLl>)
262 -> LinkedList<T::Value>;
263}
264
265pub fn linked_list<T: Strategy>(
268 element: T,
269 size: impl Into<SizeRange>,
270) -> LinkedListStrategy<T> {
271 LinkedListStrategy(statics::Map::new(vec(element, size), VecToLl))
272}
273
274mapfn! {
275 [] fn VecToBinHeap[<T : fmt::Debug + Ord>](vec: Vec<T>) -> BinaryHeap<T> {
276 vec.into()
277 }
278}
279
280opaque_strategy_wrapper! {
281 #[derive(Clone, Debug)]
285 pub struct BinaryHeapStrategy[<T>][where T : Strategy, T::Value : Ord](
286 statics::Map<VecStrategy<T>, VecToBinHeap>)
287 -> BinaryHeapValueTree<T::Tree>;
288 #[derive(Clone, Debug)]
290 pub struct BinaryHeapValueTree[<T>][where T : ValueTree, T::Value : Ord](
291 statics::Map<VecValueTree<T>, VecToBinHeap>)
292 -> BinaryHeap<T::Value>;
293}
294
295pub fn binary_heap<T: Strategy>(
298 element: T,
299 size: impl Into<SizeRange>,
300) -> BinaryHeapStrategy<T>
301where
302 T::Value: Ord,
303{
304 BinaryHeapStrategy(statics::Map::new(vec(element, size), VecToBinHeap))
305}
306
307mapfn! {
308 {#[cfg(feature = "std")]}
309 [] fn VecToHashSet[<T : fmt::Debug + Hash + Eq>](vec: Vec<T>)
310 -> HashSet<T> {
311 vec.into_iter().collect()
312 }
313}
314
315#[derive(Debug, Clone, Copy)]
316struct MinSize(usize);
317
318#[cfg(feature = "std")]
319impl<T: Eq + Hash> statics::FilterFn<HashSet<T>> for MinSize {
320 fn apply(&self, set: &HashSet<T>) -> bool {
321 set.len() >= self.0
322 }
323}
324
325opaque_strategy_wrapper! {
326 {#[cfg(feature = "std")]}
327 {#[cfg_attr(docsrs, doc(cfg(feature = "std")))]}
328 #[derive(Clone, Debug)]
332 pub struct HashSetStrategy[<T>][where T : Strategy, T::Value : Hash + Eq](
333 statics::Filter<statics::Map<VecStrategy<T>, VecToHashSet>, MinSize>)
334 -> HashSetValueTree<T::Tree>;
335 #[derive(Clone, Debug)]
337 pub struct HashSetValueTree[<T>][where T : ValueTree, T::Value : Hash + Eq](
338 statics::Filter<statics::Map<VecValueTree<T>, VecToHashSet>, MinSize>)
339 -> HashSet<T::Value>;
340}
341
342#[cfg(feature = "std")]
349#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
350pub fn hash_set<T: Strategy>(
351 element: T,
352 size: impl Into<SizeRange>,
353) -> HashSetStrategy<T>
354where
355 T::Value: Hash + Eq,
356{
357 let size = size.into();
358 HashSetStrategy(statics::Filter::new(
359 statics::Map::new(vec(element, size.clone()), VecToHashSet),
360 "HashSet minimum size".into(),
361 MinSize(size.start()),
362 ))
363}
364
365mapfn! {
366 [] fn VecToBTreeSet[<T : fmt::Debug + Ord>](vec: Vec<T>)
367 -> BTreeSet<T> {
368 vec.into_iter().collect()
369 }
370}
371
372impl<T: Ord> statics::FilterFn<BTreeSet<T>> for MinSize {
373 fn apply(&self, set: &BTreeSet<T>) -> bool {
374 set.len() >= self.0
375 }
376}
377
378opaque_strategy_wrapper! {
379 #[derive(Clone, Debug)]
383 pub struct BTreeSetStrategy[<T>][where T : Strategy, T::Value : Ord](
384 statics::Filter<statics::Map<VecStrategy<T>, VecToBTreeSet>, MinSize>)
385 -> BTreeSetValueTree<T::Tree>;
386 #[derive(Clone, Debug)]
388 pub struct BTreeSetValueTree[<T>][where T : ValueTree, T::Value : Ord](
389 statics::Filter<statics::Map<VecValueTree<T>, VecToBTreeSet>, MinSize>)
390 -> BTreeSet<T::Value>;
391}
392
393pub fn btree_set<T: Strategy>(
400 element: T,
401 size: impl Into<SizeRange>,
402) -> BTreeSetStrategy<T>
403where
404 T::Value: Ord,
405{
406 let size = size.into();
407 BTreeSetStrategy(statics::Filter::new(
408 statics::Map::new(vec(element, size.clone()), VecToBTreeSet),
409 "BTreeSet minimum size".into(),
410 MinSize(size.start()),
411 ))
412}
413
414mapfn! {
415 {#[cfg(feature = "std")]}
416 [] fn VecToHashMap[<K : fmt::Debug + Hash + Eq, V : fmt::Debug>]
417 (vec: Vec<(K, V)>) -> HashMap<K, V>
418 {
419 vec.into_iter().collect()
420 }
421}
422
423#[cfg(feature = "std")]
424impl<K: Hash + Eq, V> statics::FilterFn<HashMap<K, V>> for MinSize {
425 fn apply(&self, map: &HashMap<K, V>) -> bool {
426 map.len() >= self.0
427 }
428}
429
430opaque_strategy_wrapper! {
431 {#[cfg(feature = "std")]}
432 {#[cfg_attr(docsrs, doc(cfg(feature = "std")))]}
433 #[derive(Clone, Debug)]
437 pub struct HashMapStrategy[<K, V>]
438 [where K : Strategy, V : Strategy, K::Value : Hash + Eq](
439 statics::Filter<statics::Map<VecStrategy<(K,V)>,
440 VecToHashMap>, MinSize>)
441 -> HashMapValueTree<K::Tree, V::Tree>;
442 #[derive(Clone, Debug)]
444 pub struct HashMapValueTree[<K, V>]
445 [where K : ValueTree, V : ValueTree, K::Value : Hash + Eq](
446 statics::Filter<statics::Map<VecValueTree<TupleValueTree<(K, V)>>,
447 VecToHashMap>, MinSize>)
448 -> HashMap<K::Value, V::Value>;
449}
450
451#[cfg(feature = "std")]
459#[cfg_attr(docsrs, doc(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}