1 use super::{Duration, Instant, SystemTime, UNIX_EPOCH}
;
2 #[cfg(not(target_arch = "wasm32"))]
3 use test
::{black_box, Bencher}
;
5 macro_rules
! assert_almost_eq
{
6 ($a
:expr
, $b
:expr
) => {{
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
);
16 fn instant_monotonic() {
17 let a
= Instant
::now();
19 let b
= Instant
::now();
28 #[cfg(not(target_arch = "wasm32"))]
29 fn instant_monotonic_concurrent() -> crate::thread
::Result
<()> {
30 let threads
: Vec
<_
> = (0..8)
32 crate::thread
::spawn(|| {
33 let mut old
= Instant
::now();
34 for _
in 0..5_000_000 {
35 let new
= Instant
::now();
49 fn instant_elapsed() {
50 let a
= Instant
::now();
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
);
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
);
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`.
74 maybe_t
= maybe_t
.and_then(|t
| t
.checked_add(max_duration
));
76 assert_eq
!(maybe_t
, None
);
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());
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
);
94 fn instant_duration_since_panic() {
95 let a
= Instant
::now();
96 (a
- Duration
::SECOND
).duration_since(a
);
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
));
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
);
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
);
126 assert_almost_eq
!(b
- dur
, a
);
127 assert_almost_eq
!(a
+ dur
, b
);
130 let dur
= dur
.duration();
132 assert_almost_eq
!(b
+ dur
, a
);
133 assert_almost_eq
!(a
- dur
, b
);
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
);
141 assert_almost_eq
!(a
- second
+ second
, a
);
142 assert_almost_eq
!(a
.checked_sub(second
).unwrap().checked_add(second
).unwrap(), a
);
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
);
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`.
154 maybe_t
= maybe_t
.and_then(|t
| t
.checked_add(max_duration
));
156 assert_eq
!(maybe_t
, None
);
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());
164 fn system_time_elapsed() {
165 let a
= SystemTime
::now();
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();
175 assert_eq
!(b
- a
, Duration
::SECOND
);
177 let thirty_years
= Duration
::SECOND
* 60 * 60 * 24 * 365 * 30;
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)
183 // Otherwise let's assume that we're all running computers later than
185 if !cfg
!(target_arch
= "aarch64") && !cfg
!(target_arch
= "riscv64") {
186 assert
!(a
> thirty_years
);
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
);
195 #[cfg(all(target_has_atomic = "64", not(target_has_atomic = "128")))]
197 fn monotonizer_wrapping_backslide() {
198 use super::monotonic
::inner
::{monotonize_impl, ZERO}
;
199 use core
::sync
::atomic
::AtomicU64
;
201 let reference
= AtomicU64
::new(0);
203 let time
= match ZERO
.checked_add_duration(&Duration
::from_secs(0xffff_ffff)) {
206 // platform cannot represent u32::MAX seconds so it won't have to deal with this kind
207 // of overflow either
212 let monotonized
= monotonize_impl(&reference
, time
);
213 let expected
= ZERO
.checked_add_duration(&Duration
::from_secs(1 << 32)).unwrap();
215 monotonized
, expected
,
216 "64bit monotonizer should handle overflows in the seconds part"
220 macro_rules
! bench_instant_threaded
{
221 ($bench_name
:ident
, $thread_count
:expr
) => {
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
;
228 let running
= Arc
::new(AtomicBool
::new(true));
230 let threads
: Vec
<_
> = (0..$thread_count
)
232 let flag
= Arc
::clone(&running
);
233 crate::thread
::spawn(move || {
234 while flag
.load(Ordering
::Relaxed
) {
235 black_box(Instant
::now());
242 let a
= Instant
::now();
243 let b
= Instant
::now();
247 running
.store(false, Ordering
::Relaxed
);
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);