]> git.lizzy.rs Git - rust.git/blob - library/std/src/time/tests.rs
Rollup merge of #94839 - TaKO8Ki:suggest-using-double-colon-for-struct-field-type...
[rust.git] / library / std / src / time / tests.rs
1 use super::{Duration, Instant, SystemTime, UNIX_EPOCH};
2 #[cfg(not(target_arch = "wasm32"))]
3 use test::{black_box, Bencher};
4
5 macro_rules! assert_almost_eq {
6     ($a:expr, $b:expr) => {{
7         let (a, b) = ($a, $b);
8         if a != b {
9             let (a, b) = if a > b { (a, b) } else { (b, a) };
10             assert!(a - Duration::from_micros(1) <= b, "{:?} is not almost equal to {:?}", a, b);
11         }
12     }};
13 }
14
15 #[test]
16 fn instant_monotonic() {
17     let a = Instant::now();
18     loop {
19         let b = Instant::now();
20         assert!(b >= a);
21         if b > a {
22             break;
23         }
24     }
25 }
26
27 #[test]
28 #[cfg(not(target_arch = "wasm32"))]
29 fn instant_monotonic_concurrent() -> crate::thread::Result<()> {
30     let threads: Vec<_> = (0..8)
31         .map(|_| {
32             crate::thread::spawn(|| {
33                 let mut old = Instant::now();
34                 for _ in 0..5_000_000 {
35                     let new = Instant::now();
36                     assert!(new >= old);
37                     old = new;
38                 }
39             })
40         })
41         .collect();
42     for t in threads {
43         t.join()?;
44     }
45     Ok(())
46 }
47
48 #[test]
49 fn instant_elapsed() {
50     let a = Instant::now();
51     let _ = a.elapsed();
52 }
53
54 #[test]
55 fn instant_math() {
56     let a = Instant::now();
57     let b = Instant::now();
58     println!("a: {a:?}");
59     println!("b: {b:?}");
60     let dur = b.duration_since(a);
61     println!("dur: {dur:?}");
62     assert_almost_eq!(b - dur, a);
63     assert_almost_eq!(a + dur, b);
64
65     let second = Duration::SECOND;
66     assert_almost_eq!(a - second + second, a);
67     assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
68
69     // checked_add_duration will not panic on overflow
70     let mut maybe_t = Some(Instant::now());
71     let max_duration = Duration::from_secs(u64::MAX);
72     // in case `Instant` can store `>= now + max_duration`.
73     for _ in 0..2 {
74         maybe_t = maybe_t.and_then(|t| t.checked_add(max_duration));
75     }
76     assert_eq!(maybe_t, None);
77
78     // checked_add_duration calculates the right time and will work for another year
79     let year = Duration::from_secs(60 * 60 * 24 * 365);
80     assert_eq!(a + year, a.checked_add(year).unwrap());
81 }
82
83 #[test]
84 fn instant_math_is_associative() {
85     let now = Instant::now();
86     let offset = Duration::from_millis(5);
87     // Changing the order of instant math shouldn't change the results,
88     // especially when the expression reduces to X + identity.
89     assert_eq!((now + offset) - now, (now - now) + offset);
90 }
91
92 #[test]
93 fn instant_duration_since_saturates() {
94     let a = Instant::now();
95     assert_eq!((a - Duration::SECOND).duration_since(a), Duration::ZERO);
96 }
97
98 #[test]
99 fn instant_checked_duration_since_nopanic() {
100     let now = Instant::now();
101     let earlier = now - Duration::SECOND;
102     let later = now + Duration::SECOND;
103     assert_eq!(earlier.checked_duration_since(now), None);
104     assert_eq!(later.checked_duration_since(now), Some(Duration::SECOND));
105     assert_eq!(now.checked_duration_since(now), Some(Duration::ZERO));
106 }
107
108 #[test]
109 fn instant_saturating_duration_since_nopanic() {
110     let a = Instant::now();
111     #[allow(deprecated, deprecated_in_future)]
112     let ret = (a - Duration::SECOND).saturating_duration_since(a);
113     assert_eq!(ret, Duration::ZERO);
114 }
115
116 #[test]
117 fn system_time_math() {
118     let a = SystemTime::now();
119     let b = SystemTime::now();
120     match b.duration_since(a) {
121         Ok(Duration::ZERO) => {
122             assert_almost_eq!(a, b);
123         }
124         Ok(dur) => {
125             assert!(b > a);
126             assert_almost_eq!(b - dur, a);
127             assert_almost_eq!(a + dur, b);
128         }
129         Err(dur) => {
130             let dur = dur.duration();
131             assert!(a > b);
132             assert_almost_eq!(b + dur, a);
133             assert_almost_eq!(a - dur, b);
134         }
135     }
136
137     let second = Duration::SECOND;
138     assert_almost_eq!(a.duration_since(a - second).unwrap(), second);
139     assert_almost_eq!(a.duration_since(a + second).unwrap_err().duration(), second);
140
141     assert_almost_eq!(a - second + second, a);
142     assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
143
144     let one_second_from_epoch = UNIX_EPOCH + Duration::SECOND;
145     let one_second_from_epoch2 =
146         UNIX_EPOCH + Duration::from_millis(500) + Duration::from_millis(500);
147     assert_eq!(one_second_from_epoch, one_second_from_epoch2);
148
149     // checked_add_duration will not panic on overflow
150     let mut maybe_t = Some(SystemTime::UNIX_EPOCH);
151     let max_duration = Duration::from_secs(u64::MAX);
152     // in case `SystemTime` can store `>= UNIX_EPOCH + max_duration`.
153     for _ in 0..2 {
154         maybe_t = maybe_t.and_then(|t| t.checked_add(max_duration));
155     }
156     assert_eq!(maybe_t, None);
157
158     // checked_add_duration calculates the right time and will work for another year
159     let year = Duration::from_secs(60 * 60 * 24 * 365);
160     assert_eq!(a + year, a.checked_add(year).unwrap());
161 }
162
163 #[test]
164 fn system_time_elapsed() {
165     let a = SystemTime::now();
166     drop(a.elapsed());
167 }
168
169 #[test]
170 fn since_epoch() {
171     let ts = SystemTime::now();
172     let a = ts.duration_since(UNIX_EPOCH + Duration::SECOND).unwrap();
173     let b = ts.duration_since(UNIX_EPOCH).unwrap();
174     assert!(b > a);
175     assert_eq!(b - a, Duration::SECOND);
176
177     let thirty_years = Duration::SECOND * 60 * 60 * 24 * 365 * 30;
178
179     // Right now for CI this test is run in an emulator, and apparently the
180     // aarch64 emulator's sense of time is that we're still living in the
181     // 70s. This is also true for riscv (also qemu)
182     //
183     // Otherwise let's assume that we're all running computers later than
184     // 2000.
185     if !cfg!(target_arch = "aarch64") && !cfg!(target_arch = "riscv64") {
186         assert!(a > thirty_years);
187     }
188
189     // let's assume that we're all running computers earlier than 2090.
190     // Should give us ~70 years to fix this!
191     let hundred_twenty_years = thirty_years * 4;
192     assert!(a < hundred_twenty_years);
193 }
194
195 macro_rules! bench_instant_threaded {
196     ($bench_name:ident, $thread_count:expr) => {
197         #[bench]
198         #[cfg(not(target_arch = "wasm32"))]
199         fn $bench_name(b: &mut Bencher) -> crate::thread::Result<()> {
200             use crate::sync::atomic::{AtomicBool, Ordering};
201             use crate::sync::Arc;
202
203             let running = Arc::new(AtomicBool::new(true));
204
205             let threads: Vec<_> = (0..$thread_count)
206                 .map(|_| {
207                     let flag = Arc::clone(&running);
208                     crate::thread::spawn(move || {
209                         while flag.load(Ordering::Relaxed) {
210                             black_box(Instant::now());
211                         }
212                     })
213                 })
214                 .collect();
215
216             b.iter(|| {
217                 let a = Instant::now();
218                 let b = Instant::now();
219                 assert!(b >= a);
220             });
221
222             running.store(false, Ordering::Relaxed);
223
224             for t in threads {
225                 t.join()?;
226             }
227             Ok(())
228         }
229     };
230 }
231
232 bench_instant_threaded!(instant_contention_01_threads, 0);
233 bench_instant_threaded!(instant_contention_02_threads, 1);
234 bench_instant_threaded!(instant_contention_04_threads, 3);
235 bench_instant_threaded!(instant_contention_08_threads, 7);
236 bench_instant_threaded!(instant_contention_16_threads, 15);