Skip to content

Commit

Permalink
Rework Instant unit tests to apply to furi::time::Instant
Browse files Browse the repository at this point in the history
  • Loading branch information
str4d committed Aug 28, 2023
1 parent 3bbe95a commit fddba1c
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 57 deletions.
99 changes: 42 additions & 57 deletions crates/flipperzero/src/furi/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,14 @@ impl<'a> Sum<&'a Duration> for Duration {
}
}

#[flipperzero_test::tests]
mod tests {
use super::{ticks_to_ns, Duration, Instant, MAX_DURATION_TICKS};
use crate::println;

#[cfg(feature = "alloc")]
use {crate::furi::thread, alloc::vec::Vec};

macro_rules! assert_almost_eq {
($a:expr, $b:expr) => {{
let (a, b) = ($a, $b);
Expand All @@ -482,7 +489,7 @@ mod tests {
}

#[test]
fn instant_monotonic() {
fn instant_increases() {
let a = Instant::now();
loop {
let b = Instant::now();
Expand All @@ -493,26 +500,26 @@ mod tests {
}
}

#[cfg(feature = "alloc")]
#[test]
#[cfg(not(target_arch = "wasm32"))]
fn instant_monotonic_concurrent() -> crate::thread::Result<()> {
fn instant_increases_concurrent() {
let threads: Vec<_> = (0..8)
.map(|_| {
crate::thread::spawn(|| {
thread::spawn(|| {
let mut old = Instant::now();
let count = if cfg!(miri) { 1_000 } else { 5_000_000 };
let count = 1_000; // TODO 5_000_000 hangs; figure out why.
for _ in 0..count {
let new = Instant::now();
assert!(new >= old);
old = new;
}
0
})
})
.collect();
for t in threads {
t.join()?;
t.join();
}
Ok(())
}

#[test]
Expand All @@ -525,14 +532,14 @@ mod tests {
fn instant_math() {
let a = Instant::now();
let b = Instant::now();
println!("a: {a:?}");
println!("b: {b:?}");
println!("a: {:?}", a);
println!("b: {:?}", b);
let dur = b.duration_since(a);
println!("dur: {dur:?}");
println!("dur: {} ns", dur.as_nanos());
assert_almost_eq!(b - dur, a);
assert_almost_eq!(a + dur, b);

let second = Duration::SECOND;
let second = Duration::from_secs(1);
assert_almost_eq!(a - second + second, a);
assert_almost_eq!(
a.checked_sub(second).unwrap().checked_add(second).unwrap(),
Expand All @@ -541,16 +548,16 @@ mod tests {

// checked_add_duration will not panic on overflow
let mut maybe_t = Some(Instant::now());
let max_duration = Duration::from_secs(u64::MAX);
let max_duration = Duration::from_nanos(ticks_to_ns(u32::MAX));
// in case `Instant` can store `>= now + max_duration`.
for _ in 0..2 {
maybe_t = maybe_t.and_then(|t| t.checked_add(max_duration));
}
assert_eq!(maybe_t, None);

// checked_add_duration calculates the right time and will work for another year
let year = Duration::from_secs(60 * 60 * 24 * 365);
assert_eq!(a + year, a.checked_add(year).unwrap());
// checked_add_duration calculates the right time and will work for another week
let week = Duration::from_secs(60 * 60 * 24 * 7);
assert_eq!(a + week, a.checked_add(week).unwrap());
}

#[test]
Expand All @@ -561,36 +568,33 @@ mod tests {
// especially when the expression reduces to X + identity.
assert_eq!((now + offset) - now, (now - now) + offset);

// On any platform, `Instant` should have the same resolution as `Duration` (e.g. 1 nanosecond)
// or better. Otherwise, math will be non-associative (see #91417).
// On any platform, `Instant` should have the same resolution as `Duration`
// (i.e. 1 tick) or better. Otherwise, math will be non-associative.
let tick_nanos = ticks_to_ns(1);
let now = Instant::now();
let provided_offset = Duration::from_nanos(1);
let provided_offset = Duration::from_nanos(tick_nanos);
let later = now + provided_offset;
let measured_offset = later - now;
assert_eq!(measured_offset, provided_offset);
}

#[test]
fn instant_duration_since_saturates() {
let a = Instant::now();
assert_eq!((a - Duration::SECOND).duration_since(a), Duration::ZERO);
}

#[test]
fn instant_checked_duration_since_nopanic() {
let now = Instant::now();
let earlier = now - Duration::SECOND;
let later = now + Duration::SECOND;
let earlier = now - Duration::from_secs(1);
let later = now + Duration::from_secs(1);
assert_eq!(earlier.checked_duration_since(now), None);
assert_eq!(later.checked_duration_since(now), Some(Duration::SECOND));
assert_eq!(
later.checked_duration_since(now),
Some(Duration::from_secs(1))
);
assert_eq!(now.checked_duration_since(now), Some(Duration::ZERO));
}

#[test]
fn instant_saturating_duration_since_nopanic() {
let a = Instant::now();
#[allow(deprecated, deprecated_in_future)]
let ret = (a - Duration::SECOND).saturating_duration_since(a);
let ret = (a - Duration::from_secs(1)).saturating_duration_since(a);
assert_eq!(ret, Duration::ZERO);
}

Expand All @@ -599,9 +603,11 @@ mod tests {
// Check that the same result occurs when adding/subtracting each duration one at a time as when
// adding/subtracting them all at once.
#[track_caller]
fn check<T: Eq + Copy + Debug>(start: Option<T>, op: impl Fn(&T, Duration) -> Option<T>) {
const DURATIONS: [Duration; 2] =
[Duration::from_secs(i64::MAX as _), Duration::from_secs(50)];
fn check<T: Eq + Copy + core::fmt::Debug>(
start: Option<T>,
op: impl Fn(&T, Duration) -> Option<T>,
) {
const DURATIONS: [Duration; 2] = [Duration(MAX_DURATION_TICKS >> 1), Duration(50)];
if let Some(start) = start {
assert_eq!(
op(&start, DURATIONS.into_iter().sum()),
Expand All @@ -610,31 +616,10 @@ mod tests {
}
}

check(
SystemTime::UNIX_EPOCH.checked_sub(Duration::from_secs(100)),
SystemTime::checked_add,
);
check(
SystemTime::UNIX_EPOCH.checked_add(Duration::from_secs(100)),
SystemTime::checked_sub,
);

let instant = Instant::now();
check(
instant.checked_sub(Duration::from_secs(100)),
Instant::checked_add,
);
check(
instant.checked_sub(Duration::from_secs(i64::MAX as _)),
Instant::checked_add,
);
check(
instant.checked_add(Duration::from_secs(100)),
Instant::checked_sub,
);
check(
instant.checked_add(Duration::from_secs(i64::MAX as _)),
Instant::checked_sub,
);
check(instant.checked_sub(Duration(100)), Instant::checked_add);
check(instant.checked_sub(Duration::MAX), Instant::checked_add);
check(instant.checked_add(Duration(100)), Instant::checked_sub);
check(instant.checked_add(Duration::MAX), Instant::checked_sub);
}
}
1 change: 1 addition & 0 deletions crates/flipperzero/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ flipperzero_test::tests_runner!(
crate::furi::rng::tests,
crate::furi::string::tests,
crate::furi::sync::tests,
crate::furi::time::tests,
crate::toolbox::crc32::tests,
crate::toolbox::md5::tests,
crate::toolbox::sha256::tests,
Expand Down

0 comments on commit fddba1c

Please sign in to comment.