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
168#[cfg(feature = "frunk")]
169impl Generic for SizeRange {
170 type Repr = RangeInclusive<usize>;
171
172 fn into(self) -> Self::Repr {
174 self.0
175 }
176
177 fn from(r: Self::Repr) -> Self {
179 r.into()
180 }
181}
182
183impl Add<usize> for SizeRange {
187 type Output = SizeRange;
188
189 fn add(self, rhs: usize) -> Self::Output {
190 let (start, end) = self.start_end_incl();
191 size_range((start + rhs)..=(end + rhs))
192 }
193}
194
195#[must_use = "strategies do nothing unless used"]
203#[derive(Clone, Debug)]
204pub struct VecStrategy<T: Strategy> {
205 element: T,
206 size: SizeRange,
207}
208
209pub fn vec<T: Strategy>(
215 element: T,
216 size: impl Into<SizeRange>,
217) -> VecStrategy<T> {
218 let size = size.into();
219 size.assert_nonempty();
220 VecStrategy { element, size }
221}
222
223mapfn! {
224 [] fn VecToDeque[<T : fmt::Debug>](vec: Vec<T>) -> VecDeque<T> {
225 vec.into()
226 }
227}
228
229opaque_strategy_wrapper! {
230 #[derive(Clone, Debug)]
234 pub struct VecDequeStrategy[<T>][where T : Strategy](
235 statics::Map<VecStrategy<T>, VecToDeque>)
236 -> VecDequeValueTree<T::Tree>;
237 #[derive(Clone, Debug)]
239 pub struct VecDequeValueTree[<T>][where T : ValueTree](
240 statics::Map<VecValueTree<T>, VecToDeque>)
241 -> VecDeque<T::Value>;
242}
243
244pub fn vec_deque<T: Strategy>(
247 element: T,
248 size: impl Into<SizeRange>,
249) -> VecDequeStrategy<T> {
250 VecDequeStrategy(statics::Map::new(vec(element, size), VecToDeque))
251}
252
253mapfn! {
254 [] fn VecToLl[<T : fmt::Debug>](vec: Vec<T>) -> LinkedList<T> {
255 vec.into_iter().collect()
256 }
257}
258
259opaque_strategy_wrapper! {
260 #[derive(Clone, Debug)]
264 pub struct LinkedListStrategy[<T>][where T : Strategy](
265 statics::Map<VecStrategy<T>, VecToLl>)
266 -> LinkedListValueTree<T::Tree>;
267 #[derive(Clone, Debug)]
269 pub struct LinkedListValueTree[<T>][where T : ValueTree](
270 statics::Map<VecValueTree<T>, VecToLl>)
271 -> LinkedList<T::Value>;
272}
273
274pub fn linked_list<T: Strategy>(
277 element: T,
278 size: impl Into<SizeRange>,
279) -> LinkedListStrategy<T> {
280 LinkedListStrategy(statics::Map::new(vec(element, size), VecToLl))
281}
282
283mapfn! {
284 [] fn VecToBinHeap[<T : fmt::Debug + Ord>](vec: Vec<T>) -> BinaryHeap<T> {
285 vec.into()
286 }
287}
288
289opaque_strategy_wrapper! {
290 #[derive(Clone, Debug)]
294 pub struct BinaryHeapStrategy[<T>][where T : Strategy, T::Value : Ord](
295 statics::Map<VecStrategy<T>, VecToBinHeap>)
296 -> BinaryHeapValueTree<T::Tree>;
297 #[derive(Clone, Debug)]
299 pub struct BinaryHeapValueTree[<T>][where T : ValueTree, T::Value : Ord](
300 statics::Map<VecValueTree<T>, VecToBinHeap>)
301 -> BinaryHeap<T::Value>;
302}
303
304pub fn binary_heap<T: Strategy>(
307 element: T,
308 size: impl Into<SizeRange>,
309) -> BinaryHeapStrategy<T>
310where
311 T::Value: Ord,
312{
313 BinaryHeapStrategy(statics::Map::new(vec(element, size), VecToBinHeap))
314}
315
316mapfn! {
317 {#[cfg(feature = "std")]}
318 [] fn VecToHashSet[<T : fmt::Debug + Hash + Eq>](vec: Vec<T>)
319 -> HashSet<T> {
320 vec.into_iter().collect()
321 }
322}
323
324#[derive(Debug, Clone, Copy)]
325struct MinSize(usize);
326
327#[cfg(feature = "std")]
328impl<T: Eq + Hash> statics::FilterFn<HashSet<T>> for MinSize {
329 fn apply(&self, set: &HashSet<T>) -> bool {
330 set.len() >= self.0
331 }
332}
333
334opaque_strategy_wrapper! {
335 {#[cfg(feature = "std")]}
336 {#[cfg_attr(docsrs, doc(cfg(feature = "std")))]}
337 #[derive(Clone, Debug)]
341 pub struct HashSetStrategy[<T>][where T : Strategy, T::Value : Hash + Eq](
342 statics::Filter<statics::Map<VecStrategy<T>, VecToHashSet>, MinSize>)
343 -> HashSetValueTree<T::Tree>;
344 #[derive(Clone, Debug)]
346 pub struct HashSetValueTree[<T>][where T : ValueTree, T::Value : Hash + Eq](
347 statics::Filter<statics::Map<VecValueTree<T>, VecToHashSet>, MinSize>)
348 -> HashSet<T::Value>;
349}
350
351#[cfg(feature = "std")]
358#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
359pub fn hash_set<T: Strategy>(
360 element: T,
361 size: impl Into<SizeRange>,
362) -> HashSetStrategy<T>
363where
364 T::Value: Hash + Eq,
365{
366 let size = size.into();
367 HashSetStrategy(statics::Filter::new(
368 statics::Map::new(vec(element, size.clone()), VecToHashSet),
369 "HashSet minimum size".into(),
370 MinSize(size.start()),
371 ))
372}
373
374mapfn! {
375 [] fn VecToBTreeSet[<T : fmt::Debug + Ord>](vec: Vec<T>)
376 -> BTreeSet<T> {
377 vec.into_iter().collect()
378 }
379}
380
381impl<T: Ord> statics::FilterFn<BTreeSet<T>> for MinSize {
382 fn apply(&self, set: &BTreeSet<T>) -> bool {
383 set.len() >= self.0
384 }
385}
386
387opaque_strategy_wrapper! {
388 #[derive(Clone, Debug)]
392 pub struct BTreeSetStrategy[<T>][where T : Strategy, T::Value : Ord](
393 statics::Filter<statics::Map<VecStrategy<T>, VecToBTreeSet>, MinSize>)
394 -> BTreeSetValueTree<T::Tree>;
395 #[derive(Clone, Debug)]
397 pub struct BTreeSetValueTree[<T>][where T : ValueTree, T::Value : Ord](
398 statics::Filter<statics::Map<VecValueTree<T>, VecToBTreeSet>, MinSize>)
399 -> BTreeSet<T::Value>;
400}
401
402pub fn btree_set<T: Strategy>(
409 element: T,
410 size: impl Into<SizeRange>,
411) -> BTreeSetStrategy<T>
412where
413 T::Value: Ord,
414{
415 let size = size.into();
416 BTreeSetStrategy(statics::Filter::new(
417 statics::Map::new(vec(element, size.clone()), VecToBTreeSet),
418 "BTreeSet minimum size".into(),
419 MinSize(size.start()),
420 ))
421}
422
423mapfn! {
424 {#[cfg(feature = "std")]}
425 [] fn VecToHashMap[<K : fmt::Debug + Hash + Eq, V : fmt::Debug>]
426 (vec: Vec<(K, V)>) -> HashMap<K, V>
427 {
428 vec.into_iter().collect()
429 }
430}
431
432#[cfg(feature = "std")]
433impl<K: Hash + Eq, V> statics::FilterFn<HashMap<K, V>> for MinSize {
434 fn apply(&self, map: &HashMap<K, V>) -> bool {
435 map.len() >= self.0
436 }
437}
438
439opaque_strategy_wrapper! {
440 {#[cfg(feature = "std")]}
441 {#[cfg_attr(docsrs, doc(cfg(feature = "std")))]}
442 #[derive(Clone, Debug)]
446 pub struct HashMapStrategy[<K, V>]
447 [where K : Strategy, V : Strategy, K::Value : Hash + Eq](
448 statics::Filter<statics::Map<VecStrategy<(K,V)>,
449 VecToHashMap>, MinSize>)
450 -> HashMapValueTree<K::Tree, V::Tree>;
451 #[derive(Clone, Debug)]
453 pub struct HashMapValueTree[<K, V>]
454 [where K : ValueTree, V : ValueTree, K::Value : Hash + Eq](
455 statics::Filter<statics::Map<VecValueTree<TupleValueTree<(K, V)>>,
456 VecToHashMap>, MinSize>)
457 -> HashMap<K::Value, V::Value>;
458}
459
460#[cfg(feature = "std")]
468#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
469pub fn hash_map<K: Strategy, V: Strategy>(
470 key: K,
471 value: V,
472 size: impl Into<SizeRange>,
473) -> HashMapStrategy<K, V>
474where
475 K::Value: Hash + Eq,
476{
477 let size = size.into();
478 HashMapStrategy(statics::Filter::new(
479 statics::Map::new(vec((key, value), size.clone()), VecToHashMap),
480 "HashMap minimum size".into(),
481 MinSize(size.start()),
482 ))
483}
484
485mapfn! {
486 [] fn VecToBTreeMap[<K : fmt::Debug + Ord, V : fmt::Debug>]
487 (vec: Vec<(K, V)>) -> BTreeMap<K, V>
488 {
489 vec.into_iter().collect()
490 }
491}
492
493impl<K: Ord, V> statics::FilterFn<BTreeMap<K, V>> for MinSize {
494 fn apply(&self, map: &BTreeMap<K, V>) -> bool {
495 map.len() >= self.0
496 }
497}
498
499opaque_strategy_wrapper! {
500 #[derive(Clone, Debug)]
504 pub struct BTreeMapStrategy[<K, V>]
505 [where K : Strategy, V : Strategy, K::Value : Ord](
506 statics::Filter<statics::Map<VecStrategy<(K,V)>,
507 VecToBTreeMap>, MinSize>)
508 -> BTreeMapValueTree<K::Tree, V::Tree>;
509 #[derive(Clone, Debug)]
511 pub struct BTreeMapValueTree[<K, V>]
512 [where K : ValueTree, V : ValueTree, K::Value : Ord](
513 statics::Filter<statics::Map<VecValueTree<TupleValueTree<(K, V)>>,
514 VecToBTreeMap>, MinSize>)
515 -> BTreeMap<K::Value, V::Value>;
516}
517
518pub fn btree_map<K: Strategy, V: Strategy>(
526 key: K,
527 value: V,
528 size: impl Into<SizeRange>,
529) -> BTreeMapStrategy<K, V>
530where
531 K::Value: Ord,
532{
533 let size = size.into();
534 BTreeMapStrategy(statics::Filter::new(
535 statics::Map::new(vec((key, value), size.clone()), VecToBTreeMap),
536 "BTreeMap minimum size".into(),
537 MinSize(size.start()),
538 ))
539}
540
541#[derive(Clone, Copy, Debug)]
542enum Shrink {
543 DeleteElement(usize),
544 ShrinkElement(usize),
545}
546
547#[derive(Clone, Debug)]
549pub struct VecValueTree<T: ValueTree> {
550 elements: Vec<T>,
551 included_elements: VarBitSet,
552 min_size: usize,
553 shrink: Shrink,
554 prev_shrink: Option<Shrink>,
555}
556
557impl<T: Strategy> Strategy for VecStrategy<T> {
558 type Tree = VecValueTree<T::Tree>;
559 type Value = Vec<T::Value>;
560
561 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
562 let (start, end) = self.size.start_end_incl();
563 let max_size = sample_uniform_incl(runner, start, end);
564 let mut elements = Vec::with_capacity(max_size);
565 while elements.len() < max_size {
566 elements.push(self.element.new_tree(runner)?);
567 }
568
569 Ok(VecValueTree {
570 elements,
571 included_elements: VarBitSet::saturated(max_size),
572 min_size: start,
573 shrink: Shrink::DeleteElement(0),
574 prev_shrink: None,
575 })
576 }
577}
578
579impl<T: Strategy> Strategy for Vec<T> {
580 type Tree = VecValueTree<T::Tree>;
581 type Value = Vec<T::Value>;
582
583 fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
584 let len = self.len();
585 let elements = self
586 .iter()
587 .map(|t| t.new_tree(runner))
588 .collect::<Result<Vec<_>, Reason>>()?;
589
590 Ok(VecValueTree {
591 elements,
592 included_elements: VarBitSet::saturated(len),
593 min_size: len,
594 shrink: Shrink::ShrinkElement(0),
595 prev_shrink: None,
596 })
597 }
598}
599
600impl<T: ValueTree> ValueTree for VecValueTree<T> {
601 type Value = Vec<T::Value>;
602
603 fn current(&self) -> Vec<T::Value> {
604 self.elements
605 .iter()
606 .enumerate()
607 .filter(|&(ix, _)| self.included_elements.test(ix))
608 .map(|(_, element)| element.current())
609 .collect()
610 }
611
612 fn simplify(&mut self) -> bool {
613 if let Shrink::DeleteElement(ix) = self.shrink {
620 if ix >= self.elements.len()
623 || self.included_elements.count() == self.min_size
624 {
625 self.shrink = Shrink::ShrinkElement(0);
626 } else {
627 self.included_elements.clear(ix);
628 self.prev_shrink = Some(self.shrink);
629 self.shrink = Shrink::DeleteElement(ix + 1);
630 return true;
631 }
632 }
633
634 while let Shrink::ShrinkElement(ix) = self.shrink {
635 if ix >= self.elements.len() {
636 return false;
638 }
639
640 if !self.included_elements.test(ix) {
641 self.shrink = Shrink::ShrinkElement(ix + 1);
643 continue;
644 }
645
646 if !self.elements[ix].simplify() {
647 self.shrink = Shrink::ShrinkElement(ix + 1);
649 } else {
650 self.prev_shrink = Some(self.shrink);
651 return true;
652 }
653 }
654
655 panic!("Unexpected shrink state");
656 }
657
658 fn complicate(&mut self) -> bool {
659 match self.prev_shrink {
660 None => false,
661 Some(Shrink::DeleteElement(ix)) => {
662 self.included_elements.set(ix);
665 self.prev_shrink = None;
666 true
667 }
668 Some(Shrink::ShrinkElement(ix)) => {
669 if self.elements[ix].complicate() {
670 true
673 } else {
674 self.prev_shrink = None;
676 false
677 }
678 }
679 }
680 }
681}
682
683#[cfg(test)]
688mod test {
689 use super::*;
690
691 use crate::bits;
692
693 #[test]
694 fn test_vec() {
695 let input = vec(1usize..20usize, 5..20);
696 let mut num_successes = 0;
697
698 let mut runner = TestRunner::deterministic();
699 for _ in 0..256 {
700 let case = input.new_tree(&mut runner).unwrap();
701 let start = case.current();
702 assert!(start.len() >= 5 && start.len() < 20);
704 assert!(start.iter().map(|&v| v).collect::<VarBitSet>().len() >= 2);
706
707 let result = runner.run_one(case, |v| {
708 prop_assert!(
709 v.iter().map(|&v| v).sum::<usize>() < 9,
710 "greater than 8"
711 );
712 Ok(())
713 });
714
715 match result {
716 Ok(true) => num_successes += 1,
717 Err(TestError::Fail(_, value)) => {
718 assert!(
722 value.len() >= 5
723 && value.len() <= 9
724 && value.iter().map(|&v| v).sum::<usize>() == 9,
725 "Unexpected minimal value: {:?}",
726 value
727 );
728 }
729 e => panic!("Unexpected result: {:?}", e),
730 }
731 }
732
733 assert!(num_successes < 256);
734 }
735
736 #[test]
737 fn test_vec_sanity() {
738 check_strategy_sanity(vec(0i32..1000, 5..10), None);
739 }
740
741 #[test]
742 fn test_parallel_vec() {
743 let input =
744 vec![(1u32..10).boxed(), bits::u32::masked(0xF0u32).boxed()];
745
746 for _ in 0..256 {
747 let mut runner = TestRunner::default();
748 let mut case = input.new_tree(&mut runner).unwrap();
749
750 loop {
751 let current = case.current();
752 assert_eq!(2, current.len());
753 assert!(current[0] >= 1 && current[0] <= 10);
754 assert_eq!(0, (current[1] & !0xF0));
755
756 if !case.simplify() {
757 break;
758 }
759 }
760 }
761 }
762
763 #[cfg(feature = "std")]
764 #[test]
765 fn test_map() {
766 let input = hash_map("[ab]{3}", "a", 2..3);
768 let mut runner = TestRunner::deterministic();
769
770 for _ in 0..256 {
771 let v = input.new_tree(&mut runner).unwrap().current();
772 assert_eq!(2, v.len());
773 }
774 }
775
776 #[cfg(feature = "std")]
777 #[test]
778 fn test_set() {
779 let input = hash_set("[ab]{3}", 2..3);
781 let mut runner = TestRunner::deterministic();
782
783 for _ in 0..256 {
784 let v = input.new_tree(&mut runner).unwrap().current();
785 assert_eq!(2, v.len());
786 }
787 }
788}