Skip to main content

atomic_time/
arbitrary.rs

1use core::time::Duration;
2
3use ::arbitrary::{Arbitrary, Result, Unstructured};
4
5use crate::{AtomicDuration, AtomicOptionDuration};
6
7impl<'a> Arbitrary<'a> for AtomicDuration {
8  fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
9    <Duration as Arbitrary>::arbitrary(u).map(Self::new)
10  }
11
12  fn size_hint(depth: usize) -> (usize, Option<usize>) {
13    <Duration as Arbitrary>::size_hint(depth)
14  }
15}
16
17impl<'a> Arbitrary<'a> for AtomicOptionDuration {
18  fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
19    <Option<Duration> as Arbitrary>::arbitrary(u).map(Self::new)
20  }
21
22  fn size_hint(depth: usize) -> (usize, Option<usize>) {
23    <Option<Duration> as Arbitrary>::size_hint(depth)
24  }
25}
26
27#[cfg(feature = "std")]
28const _: () = {
29  use crate::{AtomicOptionSystemTime, AtomicSystemTime};
30  use std::time::SystemTime;
31
32  fn system_time_from_parts((seconds, nanoseconds): (u32, u32)) -> SystemTime {
33    let duration = Duration::new(
34      u64::from(seconds.min(i32::MAX as u32)),
35      nanoseconds % 1_000_000_000,
36    );
37    SystemTime::UNIX_EPOCH
38      .checked_add(duration)
39      .unwrap_or(SystemTime::UNIX_EPOCH)
40  }
41
42  impl<'a> Arbitrary<'a> for AtomicSystemTime {
43    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
44      <(u32, u32) as Arbitrary>::arbitrary(u)
45        .map(system_time_from_parts)
46        .map(Self::new)
47    }
48
49    fn size_hint(depth: usize) -> (usize, Option<usize>) {
50      <(u32, u32) as Arbitrary>::size_hint(depth)
51    }
52  }
53
54  impl<'a> Arbitrary<'a> for AtomicOptionSystemTime {
55    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
56      <Option<(u32, u32)> as Arbitrary>::arbitrary(u)
57        .map(|parts| Self::new(parts.map(system_time_from_parts)))
58    }
59
60    fn size_hint(depth: usize) -> (usize, Option<usize>) {
61      <Option<(u32, u32)> as Arbitrary>::size_hint(depth)
62    }
63  }
64};
65
66#[cfg(test)]
67mod tests {
68  use super::*;
69  use core::sync::atomic::Ordering;
70
71  #[cfg(feature = "std")]
72  use {
73    crate::{AtomicOptionSystemTime, AtomicSystemTime},
74    std::time::SystemTime,
75  };
76
77  #[test]
78  fn duration_types_are_deterministic_and_delegate_size_hints() {
79    let input = [0xff; 32];
80    let mut first_input = Unstructured::new(&input);
81    let first = AtomicDuration::arbitrary(&mut first_input).unwrap();
82    let mut second_input = Unstructured::new(&input);
83    let second = AtomicDuration::arbitrary(&mut second_input).unwrap();
84
85    assert_eq!(first.load(Ordering::SeqCst), second.load(Ordering::SeqCst));
86    assert!(first_input.len() < input.len());
87    assert_eq!(
88      <AtomicDuration as Arbitrary>::size_hint(0),
89      <Duration as Arbitrary>::size_hint(0)
90    );
91    assert_eq!(
92      <AtomicOptionDuration as Arbitrary>::size_hint(0),
93      <Option<Duration> as Arbitrary>::size_hint(0)
94    );
95  }
96
97  #[test]
98  fn duration_types_handle_none_some_and_extreme_input() {
99    let mut none_input = Unstructured::new(&[0]);
100    let none = AtomicOptionDuration::arbitrary(&mut none_input).unwrap();
101    assert_eq!(none.load(Ordering::SeqCst), None);
102
103    let mut some_input = Unstructured::new(&[1; 32]);
104    let some = AtomicOptionDuration::arbitrary(&mut some_input).unwrap();
105    assert!(some.load(Ordering::SeqCst).is_some());
106
107    let mut extreme_duration_input = Unstructured::new(&[0xff; 32]);
108    assert!(AtomicDuration::arbitrary(&mut extreme_duration_input).is_ok());
109    let mut extreme_option_input = Unstructured::new(&[0xff; 32]);
110    assert!(AtomicOptionDuration::arbitrary(&mut extreme_option_input).is_ok());
111  }
112
113  #[cfg(feature = "std")]
114  #[test]
115  fn system_time_types_are_deterministic_and_after_epoch() {
116    let input = [0xff; 32];
117    let mut first_input = Unstructured::new(&input);
118    let first = AtomicSystemTime::arbitrary(&mut first_input).unwrap();
119    let mut second_input = Unstructured::new(&input);
120    let second = AtomicSystemTime::arbitrary(&mut second_input).unwrap();
121
122    let first = first.load(Ordering::SeqCst);
123    assert_eq!(first, second.load(Ordering::SeqCst));
124    assert!(first.duration_since(SystemTime::UNIX_EPOCH).is_ok());
125    assert!(first_input.len() < input.len());
126    assert_eq!(
127      <AtomicSystemTime as Arbitrary>::size_hint(0),
128      <(u32, u32) as Arbitrary>::size_hint(0)
129    );
130    assert_eq!(
131      <AtomicOptionSystemTime as Arbitrary>::size_hint(0),
132      <Option<(u32, u32)> as Arbitrary>::size_hint(0)
133    );
134  }
135
136  #[cfg(feature = "std")]
137  #[test]
138  fn option_system_time_preserves_none_and_some() {
139    let mut none_input = Unstructured::new(&[0]);
140    let none = AtomicOptionSystemTime::arbitrary(&mut none_input).unwrap();
141    assert_eq!(none.load(Ordering::SeqCst), None);
142
143    let mut some_input = Unstructured::new(&[1; 32]);
144    let some = AtomicOptionSystemTime::arbitrary(&mut some_input).unwrap();
145    assert!(some.load(Ordering::SeqCst).is_some());
146
147    let mut extreme_input = Unstructured::new(&[0xff; 32]);
148    let extreme = AtomicSystemTime::arbitrary(&mut extreme_input).unwrap();
149    assert!(extreme
150      .load(Ordering::SeqCst)
151      .duration_since(SystemTime::UNIX_EPOCH)
152      .is_ok());
153
154    let mut extreme_option_input = Unstructured::new(&[0xff; 32]);
155    let extreme_option = AtomicOptionSystemTime::arbitrary(&mut extreme_option_input).unwrap();
156    assert!(extreme_option
157      .load(Ordering::SeqCst)
158      .is_none_or(|value| value.duration_since(SystemTime::UNIX_EPOCH).is_ok()));
159  }
160}