compact_str/features/
proptest.rs

1//! Implements the [`proptest::arbitrary::Arbitrary`] trait for [`CompactString`]
2
3use alloc::string::String;
4
5use proptest::arbitrary::StrategyFor;
6use proptest::prelude::*;
7use proptest::strategy::MapInto;
8use proptest::string::StringParam;
9
10use crate::CompactString;
11
12#[cfg_attr(docsrs, doc(cfg(feature = "proptest")))]
13impl Arbitrary for CompactString {
14    type Parameters = StringParam;
15    type Strategy = MapInto<StrategyFor<String>, Self>;
16
17    fn arbitrary_with(a: Self::Parameters) -> Self::Strategy {
18        any_with::<String>(a).prop_map_into()
19    }
20}
21
22#[cfg(test)]
23mod test {
24    use alloc::string::String;
25
26    use proptest::prelude::*;
27
28    use crate::CompactString;
29
30    const MAX_SIZE: usize = core::mem::size_of::<String>();
31
32    proptest! {
33        #[test]
34        #[cfg_attr(miri, ignore)]
35        fn proptest_sanity(compact: CompactString) {
36            let control: String = compact.clone().into();
37            assert_eq!(control, compact);
38        }
39
40        /// We rely on [`proptest`]'s `String` strategy for generating a `CompactString`. When
41        /// converting from a `String` into a `CompactString`, if it's short enough we should
42        /// eagerly inline strings
43        #[test]
44        #[cfg_attr(miri, ignore)]
45        fn proptest_does_not_inline_strings(compact: CompactString) {
46            if compact.len() <= MAX_SIZE {
47                assert!(!compact.is_heap_allocated());
48            } else {
49                assert!(compact.is_heap_allocated());
50            }
51        }
52    }
53}