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