proptest/
collection.rs

1//-
2// Copyright 2017, 2018 The proptest developers
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10//! Strategies for generating `std::collections` of values.
11
12use 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//==============================================================================
31// SizeRange
32//==============================================================================
33
34/// The minimum and maximum range/bounds on the size of a collection.
35/// The interval must form a subset of `[0, std::usize::MAX)`.
36///
37/// A value like `0..=std::usize::MAX` will still be accepted but will silently
38/// truncate the maximum to `std::usize::MAX - 1`.
39///
40/// The `Default` is `0..100`.
41#[derive(Clone, PartialEq, Eq, Hash, Debug)]
42pub struct SizeRange(Range<usize>);
43
44/// Creates a `SizeRange` from some value that is convertible into it.
45pub fn size_range(from: impl Into<SizeRange>) -> SizeRange {
46    from.into()
47}
48
49impl Default for SizeRange {
50    /// Constructs a `SizeRange` equivalent to `size_range(0..100)`.
51    fn default() -> Self {
52        size_range(0..100)
53    }
54}
55
56impl SizeRange {
57    /// Creates a `SizeBounds` from a `RangeInclusive<usize>`.
58    pub fn new(range: RangeInclusive<usize>) -> Self {
59        range.into()
60    }
61
62    // Don't rely on these existing internally:
63
64    /// Merges self together with some other argument producing a product
65    /// type expected by some implementations of `A: Arbitrary` in
66    /// `A::Parameters`. This can be more ergonomic to work with and may
67    /// help type inference.
68    pub fn with<X>(self, and: X) -> product_type![Self, X] {
69        product_pack![self, and]
70    }
71
72    /// Merges self together with some other argument generated with a
73    /// default value producing a product type expected by some
74    /// implementations of `A: Arbitrary` in `A::Parameters`.
75    /// This can be more ergonomic to work with and may help type inference.
76    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    /// Extract the ends `[low, high]` of a `SizeRange`.
85    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
120/// Given `(low: usize, high: usize)`,
121/// then a size range of `[low..high)` is the result.
122impl From<(usize, usize)> for SizeRange {
123    fn from((low, high): (usize, usize)) -> Self {
124        size_range(low..high)
125    }
126}
127
128/// Given `exact`, then a size range of `[exact, exact]` is the result.
129impl From<usize> for SizeRange {
130    fn from(exact: usize) -> Self {
131        size_range(exact..=exact)
132    }
133}
134
135/// Given `..high`, then a size range `[0, high)` is the result.
136impl From<RangeTo<usize>> for SizeRange {
137    fn from(high: RangeTo<usize>) -> Self {
138        size_range(0..high.end)
139    }
140}
141
142/// Given `low .. high`, then a size range `[low, high)` is the result.
143impl From<Range<usize>> for SizeRange {
144    fn from(r: Range<usize>) -> Self {
145        SizeRange(r)
146    }
147}
148
149/// Given `low ..= high`, then a size range `[low, high]` is the result.
150impl 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
156/// Given `..=high`, then a size range `[0, high]` is the result.
157impl 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    /// Converts the `SizeRange` into `Range<usize>`.
168    fn into(self) -> Self::Repr {
169        self.0
170    }
171
172    /// Converts `RangeInclusive<usize>` into `SizeRange`.
173    fn from(r: Self::Repr) -> Self {
174        r.into()
175    }
176}
177
178/// Adds `usize` to both start and end of the bounds.
179///
180/// Panics if adding to either end overflows `usize`.
181impl 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//==============================================================================
191// Strategies
192//==============================================================================
193
194/// Strategy to create `Vec`s with a length in a certain range.
195///
196/// Created by the `vec()` function in the same module.
197#[must_use = "strategies do nothing unless used"]
198#[derive(Clone, Debug)]
199pub struct VecStrategy<T: Strategy> {
200    element: T,
201    size: SizeRange,
202}
203
204/// Create a strategy to generate `Vec`s containing elements drawn from
205/// `element` and with a size range given by `size`.
206///
207/// To make a `Vec` with a fixed number of elements, each with its own
208/// strategy, you can instead make a `Vec` of strategies (boxed if necessary).
209pub 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    /// Strategy to create `VecDeque`s with a length in a certain range.
226    ///
227    /// Created by the `vec_deque()` function in the same module.
228    #[derive(Clone, Debug)]
229    pub struct VecDequeStrategy[<T>][where T : Strategy](
230        statics::Map<VecStrategy<T>, VecToDeque>)
231        -> VecDequeValueTree<T::Tree>;
232    /// `ValueTree` corresponding to `VecDequeStrategy`.
233    #[derive(Clone, Debug)]
234    pub struct VecDequeValueTree[<T>][where T : ValueTree](
235        statics::Map<VecValueTree<T>, VecToDeque>)
236        -> VecDeque<T::Value>;
237}
238
239/// Create a strategy to generate `VecDeque`s containing elements drawn from
240/// `element` and with a size range given by `size`.
241pub 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    /// Strategy to create `LinkedList`s with a length in a certain range.
256    ///
257    /// Created by the `linkedlist()` function in the same module.
258    #[derive(Clone, Debug)]
259    pub struct LinkedListStrategy[<T>][where T : Strategy](
260        statics::Map<VecStrategy<T>, VecToLl>)
261        -> LinkedListValueTree<T::Tree>;
262    /// `ValueTree` corresponding to `LinkedListStrategy`.
263    #[derive(Clone, Debug)]
264    pub struct LinkedListValueTree[<T>][where T : ValueTree](
265        statics::Map<VecValueTree<T>, VecToLl>)
266        -> LinkedList<T::Value>;
267}
268
269/// Create a strategy to generate `LinkedList`s containing elements drawn from
270/// `element` and with a size range given by `size`.
271pub 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    /// Strategy to create `BinaryHeap`s with a length in a certain range.
286    ///
287    /// Created by the `binary_heap()` function in the same module.
288    #[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    /// `ValueTree` corresponding to `BinaryHeapStrategy`.
293    #[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
299/// Create a strategy to generate `BinaryHeap`s containing elements drawn from
300/// `element` and with a size range given by `size`.
301pub 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    /// Strategy to create `HashSet`s with a length in a certain range.
332    ///
333    /// Created by the `hash_set()` function in the same module.
334    #[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    /// `ValueTree` corresponding to `HashSetStrategy`.
339    #[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/// Create a strategy to generate `HashSet`s containing elements drawn from
346/// `element` and with a size range given by `size`.
347///
348/// This strategy will implicitly do local rejects to ensure that the `HashSet`
349/// has at least the minimum number of elements, in case `element` should
350/// produce duplicate values.
351#[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    /// Strategy to create `BTreeSet`s with a length in a certain range.
382    ///
383    /// Created by the `btree_set()` function in the same module.
384    #[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    /// `ValueTree` corresponding to `BTreeSetStrategy`.
389    #[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
395/// Create a strategy to generate `BTreeSet`s containing elements drawn from
396/// `element` and with a size range given by `size`.
397///
398/// This strategy will implicitly do local rejects to ensure that the
399/// `BTreeSet` has at least the minimum number of elements, in case `element`
400/// should produce duplicate values.
401pub 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    /// Strategy to create `HashMap`s with a length in a certain range.
435    ///
436    /// Created by the `hash_map()` function in the same module.
437    #[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    /// `ValueTree` corresponding to `HashMapStrategy`.
444    #[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/// Create a strategy to generate `HashMap`s containing keys and values drawn
453/// from `key` and `value` respectively, and with a size within the given
454/// range.
455///
456/// This strategy will implicitly do local rejects to ensure that the `HashMap`
457/// has at least the minimum number of elements, in case `key` should produce
458/// duplicate values.
459#[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    /// Strategy to create `BTreeMap`s with a length in a certain range.
492    ///
493    /// Created by the `btree_map()` function in the same module.
494    #[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    /// `ValueTree` corresponding to `BTreeMapStrategy`.
501    #[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
509/// Create a strategy to generate `BTreeMap`s containing keys and values drawn
510/// from `key` and `value` respectively, and with a size within the given
511/// range.
512///
513/// This strategy will implicitly do local rejects to ensure that the
514/// `BTreeMap` has at least the minimum number of elements, in case `key`
515/// should produce duplicate values.
516pub 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/// `ValueTree` corresponding to `VecStrategy`.
539#[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        // The overall strategy here is to iteratively delete elements from the
605        // list until we can do so no further, then to shrink each remaining
606        // element in sequence.
607        //
608        // For `complicate()`, we simply undo the last shrink operation, if
609        // there was any.
610        if let Shrink::DeleteElement(ix) = self.shrink {
611            // Can't delete an element if beyond the end of the vec or if it
612            // would put us under the minimum length.
613            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                // Nothing more we can do
628                return false;
629            }
630
631            if !self.included_elements.test(ix) {
632                // No use shrinking something we're not including.
633                self.shrink = Shrink::ShrinkElement(ix + 1);
634                continue;
635            }
636
637            if !self.elements[ix].simplify() {
638                // Move on to the next element
639                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                // Undo the last item we deleted. Can't complicate any further,
654                // so unset prev_shrink.
655                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                    // Don't unset prev_shrink; we may be able to complicate
662                    // again.
663                    true
664                } else {
665                    // Can't complicate the last element any further.
666                    self.prev_shrink = None;
667                    false
668                }
669            }
670        }
671    }
672}
673
674//==============================================================================
675// Tests
676//==============================================================================
677
678#[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            // Has correct length
694            assert!(start.len() >= 5 && start.len() < 20);
695            // Has at least 2 distinct values
696            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                    // The minimal case always has between 5 (due to min
710                    // length) and 9 (min element value = 1) elements, and
711                    // always sums to exactly 9.
712                    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        // Only 8 possible keys
758        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        // Only 8 possible values
771        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}