]> git.proxmox.com Git - rustc.git/blob - library/std/src/time/tests.rs
New upstream version 1.56.0~beta.4+dfsg1
[rustc.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 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 #[should_panic]
94 fn instant_duration_since_panic() {
95 let a = Instant::now();
96 (a - Duration::SECOND).duration_since(a);
97 }
98
99 #[test]
100 fn instant_checked_duration_since_nopanic() {
101 let now = Instant::now();
102 let earlier = now - Duration::SECOND;
103 let later = now + Duration::SECOND;
104 assert_eq!(earlier.checked_duration_since(now), None);
105 assert_eq!(later.checked_duration_since(now), Some(Duration::SECOND));
106 assert_eq!(now.checked_duration_since(now), Some(Duration::ZERO));
107 }
108
109 #[test]
110 fn instant_saturating_duration_since_nopanic() {
111 let a = Instant::now();
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 #[cfg(all(target_has_atomic = "64", not(target_has_atomic = "128")))]
196 #[test]
197 fn monotonizer_wrapping_backslide() {
198 use super::monotonic::inner::{monotonize_impl, ZERO};
199 use core::sync::atomic::AtomicU64;
200
201 let reference = AtomicU64::new(0);
202
203 let time = match ZERO.checked_add_duration(&Duration::from_secs(0xffff_ffff)) {
204 Some(time) => time,
205 None => {
206 // platform cannot represent u32::MAX seconds so it won't have to deal with this kind
207 // of overflow either
208 return;
209 }
210 };
211
212 let monotonized = monotonize_impl(&reference, time);
213 let expected = ZERO.checked_add_duration(&Duration::from_secs(1 << 32)).unwrap();
214 assert_eq!(
215 monotonized, expected,
216 "64bit monotonizer should handle overflows in the seconds part"
217 );
218 }
219
220 macro_rules! bench_instant_threaded {
221 ($bench_name:ident, $thread_count:expr) => {
222 #[bench]
223 #[cfg(not(target_arch = "wasm32"))]
224 fn $bench_name(b: &mut Bencher) -> crate::thread::Result<()> {
225 use crate::sync::atomic::{AtomicBool, Ordering};
226 use crate::sync::Arc;
227
228 let running = Arc::new(AtomicBool::new(true));
229
230 let threads: Vec<_> = (0..$thread_count)
231 .map(|_| {
232 let flag = Arc::clone(&running);
233 crate::thread::spawn(move || {
234 while flag.load(Ordering::Relaxed) {
235 black_box(Instant::now());
236 }
237 })
238 })
239 .collect();
240
241 b.iter(|| {
242 let a = Instant::now();
243 let b = Instant::now();
244 assert!(b >= a);
245 });
246
247 running.store(false, Ordering::Relaxed);
248
249 for t in threads {
250 t.join()?;
251 }
252 Ok(())
253 }
254 };
255 }
256
257 bench_instant_threaded!(instant_contention_01_threads, 0);
258 bench_instant_threaded!(instant_contention_02_threads, 1);
259 bench_instant_threaded!(instant_contention_04_threads, 3);
260 bench_instant_threaded!(instant_contention_08_threads, 7);
261 bench_instant_threaded!(instant_contention_16_threads, 15);