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}