proptest/
bits.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 working with bit sets.
11//!
12//! Besides `BitSet` itself, this also defines strategies for all the primitive
13//! integer types. These strategies are appropriate for integers which are used
14//! as bit flags, etc; e.g., where the most reasonable simplification of `64`
15//! is `0` (clearing one bit) and not `63` (clearing one bit but setting 6
16//! others). For integers treated as numeric values, see the corresponding
17//! modules of the `num` module instead.
18
19use crate::std_facade::{fmt, Vec};
20use core::marker::PhantomData;
21use core::mem;
22
23#[cfg(feature = "bit-set")]
24use bit_set::BitSet;
25use rand::{self, seq::IteratorRandom, Rng};
26
27use crate::collection::SizeRange;
28use crate::num::sample_uniform_incl;
29use crate::strategy::*;
30use crate::test_runner::*;
31
32/// Trait for types which can be handled with `BitSetStrategy`.
33#[cfg_attr(feature = "cargo-clippy", allow(len_without_is_empty))]
34pub trait BitSetLike: Clone + fmt::Debug {
35    /// Create a new value of `Self` with space for up to `max` bits, all
36    /// initialised to zero.
37    fn new_bitset(max: usize) -> Self;
38    /// Return an upper bound on the greatest bit set _plus one_.
39    fn len(&self) -> usize;
40    /// Test whether the given bit is set.
41    fn test(&self, ix: usize) -> bool;
42    /// Set the given bit.
43    fn set(&mut self, ix: usize);
44    /// Clear the given bit.
45    fn clear(&mut self, ix: usize);
46    /// Return the number of bits set.
47    ///
48    /// This has a default for backwards compatibility, which simply does a
49    /// linear scan through the bits. Implementations are strongly encouraged
50    /// to override this.
51    fn count(&self) -> usize {
52        let mut n = 0;
53        for i in 0..self.len() {
54            if self.test(i) {
55                n += 1;
56            }
57        }
58        n
59    }
60}
61
62macro_rules! int_bitset {
63    ($typ:ty) => {
64        impl BitSetLike for $typ {
65            fn new_bitset(_: usize) -> Self {
66                0
67            }
68            fn len(&self) -> usize {
69                mem::size_of::<$typ>() * 8
70            }
71            fn test(&self, ix: usize) -> bool {
72                0 != (*self & ((1 as $typ) << ix))
73            }
74            fn set(&mut self, ix: usize) {
75                *self |= (1 as $typ) << ix;
76            }
77            fn clear(&mut self, ix: usize) {
78                *self &= !((1 as $typ) << ix);
79            }
80            fn count(&self) -> usize {
81                self.count_ones() as usize
82            }
83        }
84    };
85}
86int_bitset!(u8);
87int_bitset!(u16);
88int_bitset!(u32);
89int_bitset!(u64);
90int_bitset!(usize);
91int_bitset!(i8);
92int_bitset!(i16);
93int_bitset!(i32);
94int_bitset!(i64);
95int_bitset!(isize);
96
97#[cfg(feature = "bit-set")]
98impl BitSetLike for BitSet {
99    fn new_bitset(max: usize) -> Self {
100        BitSet::with_capacity(max)
101    }
102
103    fn len(&self) -> usize {
104        self.capacity()
105    }
106
107    fn test(&self, bit: usize) -> bool {
108        self.contains(bit)
109    }
110
111    fn set(&mut self, bit: usize) {
112        self.insert(bit);
113    }
114
115    fn clear(&mut self, bit: usize) {
116        self.remove(bit);
117    }
118
119    fn count(&self) -> usize {
120        self.len()
121    }
122}
123
124impl BitSetLike for Vec<bool> {
125    fn new_bitset(max: usize) -> Self {
126        vec![false; max]
127    }
128
129    fn len(&self) -> usize {
130        self.len()
131    }
132
133    fn test(&self, bit: usize) -> bool {
134        if bit >= self.len() {
135            false
136        } else {
137            self[bit]
138        }
139    }
140
141    fn set(&mut self, bit: usize) {
142        if bit >= self.len() {
143            self.resize(bit + 1, false);
144        }
145
146        self[bit] = true;
147    }
148
149    fn clear(&mut self, bit: usize) {
150        if bit < self.len() {
151            self[bit] = false;
152        }
153    }
154
155    fn count(&self) -> usize {
156        self.iter().filter(|&&b| b).count()
157    }
158}
159
160/// Generates values as a set of bits between the two bounds.
161///
162/// Values are generated by uniformly setting individual bits to 0
163/// or 1 between the bounds. Shrinking iteratively clears bits.
164#[must_use = "strategies do nothing unless used"]
165#[derive(Clone, Copy, Debug)]
166pub struct BitSetStrategy<T: BitSetLike> {
167    min: usize,
168    max: usize,
169    mask: Option<T>,
170}
171
172impl<T: BitSetLike> BitSetStrategy<T> {
173    /// Create a strategy which generates values where bits between `min`
174    /// (inclusive) and `max` (exclusive) may be set.
175    ///
176    /// Due to the generics, the functions in the typed submodules are usually
177    /// preferable to calling this directly.
178    pub fn new(min: usize, max: usize) -> Self {
179        BitSetStrategy {
180            min,
181            max,
182            mask: None,
183        }
184    }
185
186    /// Create a strategy which generates values where any bits set (and only
187    /// those bits) in `mask` may be set.
188    pub fn masked(mask: T) -> Self {
189        BitSetStrategy {
190            min: 0,
191            max: mask.len(),
192            mask: Some(mask),
193        }
194    }
195}
196
197impl<T: BitSetLike> Strategy for BitSetStrategy<T> {
198    type Tree = BitSetValueTree<T>;
199    type Value = T;
200
201    fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
202        let mut inner = T::new_bitset(self.max);
203        for bit in self.min..self.max {
204            if self.mask.as_ref().map_or(true, |mask| mask.test(bit))
205                && runner.rng().gen()
206            {
207                inner.set(bit);
208            }
209        }
210
211        Ok(BitSetValueTree {
212            inner,
213            shrink: self.min,
214            prev_shrink: None,
215            min_count: 0,
216        })
217    }
218}
219
220/// Generates bit sets with a particular number of bits set.
221///
222/// Specifically, this strategy is given both a size range and a bit range. To
223/// produce a new value, it selects a size, then uniformly selects that many
224/// bits from within the bit range.
225///
226/// Shrinking happens as with [`BitSetStrategy`](struct.BitSetStrategy.html).
227#[derive(Clone, Debug)]
228#[must_use = "strategies do nothing unless used"]
229pub struct SampledBitSetStrategy<T: BitSetLike> {
230    size: SizeRange,
231    bits: SizeRange,
232    _marker: PhantomData<T>,
233}
234
235impl<T: BitSetLike> SampledBitSetStrategy<T> {
236    /// Create a strategy which generates values where bits within the bounds
237    /// given by `bits` may be set. The number of bits that are set is chosen
238    /// to be in the range given by `size`.
239    ///
240    /// Due to the generics, the functions in the typed submodules are usually
241    /// preferable to calling this directly.
242    ///
243    /// ## Panics
244    ///
245    /// Panics if `size` includes a value that is greater than the number of
246    /// bits in `bits`.
247    pub fn new(size: impl Into<SizeRange>, bits: impl Into<SizeRange>) -> Self {
248        let size = size.into();
249        let bits = bits.into();
250        size.assert_nonempty();
251
252        let available_bits = bits.end_excl() - bits.start();
253        assert!(
254            size.end_excl() <= available_bits + 1,
255            "Illegal SampledBitSetStrategy: have {} bits available, \
256             but requested size is {}..{}",
257            available_bits,
258            size.start(),
259            size.end_excl()
260        );
261        SampledBitSetStrategy {
262            size,
263            bits,
264            _marker: PhantomData,
265        }
266    }
267}
268
269impl<T: BitSetLike> Strategy for SampledBitSetStrategy<T> {
270    type Tree = BitSetValueTree<T>;
271    type Value = T;
272
273    fn new_tree(&self, runner: &mut TestRunner) -> NewTree<Self> {
274        let mut bits = T::new_bitset(self.bits.end_excl());
275        let count = sample_uniform_incl(
276            runner,
277            self.size.start(),
278            self.size.end_incl(),
279        );
280        if bits.len() < count {
281            panic!("not enough bits to sample");
282        }
283
284        for bit in self.bits.iter().choose_multiple(runner.rng(), count) {
285            bits.set(bit);
286        }
287
288        Ok(BitSetValueTree {
289            inner: bits,
290            shrink: self.bits.start(),
291            prev_shrink: None,
292            min_count: self.size.start(),
293        })
294    }
295}
296
297/// Value tree produced by `BitSetStrategy` and `SampledBitSetStrategy`.
298#[derive(Clone, Copy, Debug)]
299pub struct BitSetValueTree<T: BitSetLike> {
300    inner: T,
301    shrink: usize,
302    prev_shrink: Option<usize>,
303    min_count: usize,
304}
305
306impl<T: BitSetLike> ValueTree for BitSetValueTree<T> {
307    type Value = T;
308
309    fn current(&self) -> T {
310        self.inner.clone()
311    }
312
313    fn simplify(&mut self) -> bool {
314        if self.inner.count() <= self.min_count {
315            return false;
316        }
317
318        while self.shrink < self.inner.len() && !self.inner.test(self.shrink) {
319            self.shrink += 1;
320        }
321
322        if self.shrink >= self.inner.len() {
323            self.prev_shrink = None;
324            false
325        } else {
326            self.prev_shrink = Some(self.shrink);
327            self.inner.clear(self.shrink);
328            self.shrink += 1;
329            true
330        }
331    }
332
333    fn complicate(&mut self) -> bool {
334        if let Some(bit) = self.prev_shrink.take() {
335            self.inner.set(bit);
336            true
337        } else {
338            false
339        }
340    }
341}
342
343macro_rules! int_api {
344    ($typ:ident, $max:expr) => {
345        #[allow(missing_docs)]
346        pub mod $typ {
347            use super::*;
348
349            /// Generates integers where all bits may be set.
350            pub const ANY: BitSetStrategy<$typ> = BitSetStrategy {
351                min: 0,
352                max: $max,
353                mask: None,
354            };
355
356            /// Generates values where bits between the given bounds may be
357            /// set.
358            pub fn between(min: usize, max: usize) -> BitSetStrategy<$typ> {
359                BitSetStrategy::new(min, max)
360            }
361
362            /// Generates values where any bits set in `mask` (and no others)
363            /// may be set.
364            pub fn masked(mask: $typ) -> BitSetStrategy<$typ> {
365                BitSetStrategy::masked(mask)
366            }
367
368            /// Create a strategy which generates values where bits within the
369            /// bounds given by `bits` may be set. The number of bits that are
370            /// set is chosen to be in the range given by `size`.
371            ///
372            /// ## Panics
373            ///
374            /// Panics if `size` includes a value that is greater than the
375            /// number of bits in `bits`.
376            pub fn sampled(
377                size: impl Into<SizeRange>,
378                bits: impl Into<SizeRange>,
379            ) -> SampledBitSetStrategy<$typ> {
380                SampledBitSetStrategy::new(size, bits)
381            }
382        }
383    };
384}
385
386int_api!(u8, 8);
387int_api!(u16, 16);
388int_api!(u32, 32);
389int_api!(u64, 64);
390int_api!(i8, 8);
391int_api!(i16, 16);
392int_api!(i32, 32);
393int_api!(i64, 64);
394
395macro_rules! minimal_api {
396    ($md:ident, $typ:ty) => {
397        #[allow(missing_docs)]
398        pub mod $md {
399            use super::*;
400
401            /// Generates values where bits between the given bounds may be
402            /// set.
403            pub fn between(min: usize, max: usize) -> BitSetStrategy<$typ> {
404                BitSetStrategy::new(min, max)
405            }
406
407            /// Generates values where any bits set in `mask` (and no others)
408            /// may be set.
409            pub fn masked(mask: $typ) -> BitSetStrategy<$typ> {
410                BitSetStrategy::masked(mask)
411            }
412
413            /// Create a strategy which generates values where bits within the
414            /// bounds given by `bits` may be set. The number of bits that are
415            /// set is chosen to be in the range given by `size`.
416            ///
417            /// ## Panics
418            ///
419            /// Panics if `size` includes a value that is greater than the
420            /// number of bits in `bits`.
421            pub fn sampled(
422                size: impl Into<SizeRange>,
423                bits: impl Into<SizeRange>,
424            ) -> SampledBitSetStrategy<$typ> {
425                SampledBitSetStrategy::new(size, bits)
426            }
427        }
428    };
429}
430minimal_api!(usize, usize);
431minimal_api!(isize, isize);
432#[cfg(feature = "bit-set")]
433minimal_api!(bitset, BitSet);
434minimal_api!(bool_vec, Vec<bool>);
435
436pub(crate) mod varsize {
437    use super::*;
438    use core::iter::FromIterator;
439
440    #[cfg(feature = "bit-set")]
441    type Inner = BitSet;
442    #[cfg(not(feature = "bit-set"))]
443    type Inner = Vec<bool>;
444
445    #[derive(Debug, Clone)]
446    pub(crate) struct VarBitSet(Inner);
447
448    impl VarBitSet {
449        pub(crate) fn saturated(len: usize) -> Self {
450            (0..len).collect::<VarBitSet>()
451        }
452
453        #[cfg(not(feature = "bit-set"))]
454        pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = usize> + 'a {
455            (0..self.len()).into_iter().filter(move |&ix| self.test(ix))
456        }
457
458        #[cfg(feature = "bit-set")]
459        pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item = usize> + 'a {
460            self.0.iter()
461        }
462    }
463
464    impl BitSetLike for VarBitSet {
465        fn new_bitset(max: usize) -> Self {
466            VarBitSet(Inner::new_bitset(max))
467        }
468
469        fn len(&self) -> usize {
470            BitSetLike::len(&self.0)
471        }
472
473        fn test(&self, bit: usize) -> bool {
474            BitSetLike::test(&self.0, bit)
475        }
476
477        fn set(&mut self, bit: usize) {
478            BitSetLike::set(&mut self.0, bit);
479        }
480
481        fn clear(&mut self, bit: usize) {
482            BitSetLike::clear(&mut self.0, bit);
483        }
484
485        fn count(&self) -> usize {
486            BitSetLike::count(&self.0)
487        }
488    }
489
490    impl FromIterator<usize> for VarBitSet {
491        fn from_iter<T: IntoIterator<Item = usize>>(iter: T) -> Self {
492            let mut bits = VarBitSet::new_bitset(0);
493            for bit in iter {
494                bits.set(bit);
495            }
496            bits
497        }
498    }
499
500    /*
501    pub(crate) fn between(min: usize, max: usize) -> BitSetStrategy<VarBitSet> {
502        BitSetStrategy::new(min, max)
503    }
504
505    pub(crate) fn masked(mask: VarBitSet) -> BitSetStrategy<VarBitSet> {
506        BitSetStrategy::masked(mask)
507    }
508    */
509
510    pub(crate) fn sampled(
511        size: impl Into<SizeRange>,
512        bits: impl Into<SizeRange>,
513    ) -> SampledBitSetStrategy<VarBitSet> {
514        SampledBitSetStrategy::new(size, bits)
515    }
516}
517
518pub(crate) use self::varsize::VarBitSet;
519
520#[cfg(test)]
521mod test {
522    use super::*;
523
524    #[test]
525    fn generates_values_in_range() {
526        let input = u32::between(4, 8);
527
528        let mut runner = TestRunner::default();
529        for _ in 0..256 {
530            let value = input.new_tree(&mut runner).unwrap().current();
531            assert!(0 == value & !0xF0u32, "Generate value {}", value);
532        }
533    }
534
535    #[test]
536    fn generates_values_in_mask() {
537        let mut accum = 0;
538
539        let mut runner = TestRunner::deterministic();
540        let input = u32::masked(0xdeadbeef);
541        for _ in 0..1024 {
542            accum |= input.new_tree(&mut runner).unwrap().current();
543        }
544
545        assert_eq!(0xdeadbeef, accum);
546    }
547
548    #[cfg(feature = "bit-set")]
549    #[test]
550    fn mask_bounds_for_bitset_correct() {
551        let mut seen_0 = false;
552        let mut seen_2 = false;
553
554        let mut mask = BitSet::new();
555        mask.insert(0);
556        mask.insert(2);
557
558        let mut runner = TestRunner::deterministic();
559        let input = bitset::masked(mask);
560        for _ in 0..32 {
561            let v = input.new_tree(&mut runner).unwrap().current();
562            seen_0 |= v.contains(0);
563            seen_2 |= v.contains(2);
564        }
565
566        assert!(seen_0);
567        assert!(seen_2);
568    }
569
570    #[test]
571    fn mask_bounds_for_vecbool_correct() {
572        let mut seen_0 = false;
573        let mut seen_2 = false;
574
575        let mask = vec![true, false, true, false];
576
577        let mut runner = TestRunner::deterministic();
578        let input = bool_vec::masked(mask);
579        for _ in 0..32 {
580            let v = input.new_tree(&mut runner).unwrap().current();
581            assert_eq!(4, v.len());
582            seen_0 |= v[0];
583            seen_2 |= v[2];
584        }
585
586        assert!(seen_0);
587        assert!(seen_2);
588    }
589
590    #[test]
591    fn shrinks_to_zero() {
592        let input = u32::between(4, 24);
593
594        let mut runner = TestRunner::default();
595        for _ in 0..256 {
596            let mut value = input.new_tree(&mut runner).unwrap();
597            let mut prev = value.current();
598            while value.simplify() {
599                let v = value.current();
600                assert!(
601                    1 == (prev & !v).count_ones(),
602                    "Shrank from {} to {}",
603                    prev,
604                    v
605                );
606                prev = v;
607            }
608
609            assert_eq!(0, value.current());
610        }
611    }
612
613    #[test]
614    fn complicates_to_previous() {
615        let input = u32::between(4, 24);
616
617        let mut runner = TestRunner::default();
618        for _ in 0..256 {
619            let mut value = input.new_tree(&mut runner).unwrap();
620            let orig = value.current();
621            if value.simplify() {
622                assert!(value.complicate());
623                assert_eq!(orig, value.current());
624            }
625        }
626    }
627
628    #[test]
629    fn sampled_selects_correct_sizes_and_bits() {
630        let input = u32::sampled(4..8, 10..20);
631        let mut seen_counts = [0; 32];
632        let mut seen_bits = [0; 32];
633
634        let mut runner = TestRunner::deterministic();
635        for _ in 0..2048 {
636            let value = input.new_tree(&mut runner).unwrap().current();
637            let count = value.count_ones() as usize;
638            assert!(count >= 4 && count < 8);
639            seen_counts[count] += 1;
640
641            for bit in 0..32 {
642                if 0 != value & (1 << bit) {
643                    assert!(bit >= 10 && bit < 20);
644                    seen_bits[bit] += value;
645                }
646            }
647        }
648
649        for i in 4..8 {
650            assert!(seen_counts[i] >= 256 && seen_counts[i] < 1024);
651        }
652
653        let least_seen_bit_count =
654            seen_bits[10..20].iter().cloned().min().unwrap();
655        let most_seen_bit_count =
656            seen_bits[10..20].iter().cloned().max().unwrap();
657        assert_eq!(1, most_seen_bit_count / least_seen_bit_count);
658    }
659
660    #[test]
661    fn sampled_doesnt_shrink_below_min_size() {
662        let input = u32::sampled(4..8, 10..20);
663
664        let mut runner = TestRunner::default();
665        for _ in 0..256 {
666            let mut value = input.new_tree(&mut runner).unwrap();
667            while value.simplify() {}
668
669            assert_eq!(4, value.current().count_ones());
670        }
671    }
672
673    #[test]
674    fn test_sanity() {
675        check_strategy_sanity(u32::masked(0xdeadbeef), None);
676    }
677}