diff --git a/measure/src/measure.rs b/measure/src/measure.rs index 2dbf037472..1e96d68fda 100644 --- a/measure/src/measure.rs +++ b/measure/src/measure.rs @@ -85,69 +85,31 @@ impl fmt::Display for Measure { #[cfg(test)] mod tests { - use { - super::*, - std::{fmt::Debug, thread::sleep}, - }; + use {super::*, std::thread::sleep}; #[test] fn test_measure() { + let test_duration = Duration::from_millis(100); let mut measure = Measure::start("test"); - sleep(Duration::from_millis(100)); + sleep(test_duration); measure.stop(); - - // We have observed failures with margins of 10%, when CI machines are very busy, running - // multiple tests in parallel. As we are not testing the timer functionality itself, it is - // probably OK to increase the margins to 20%. - - assert!(measure.as_s() >= 0.08f32 && measure.as_s() <= 0.12f32); - assert!(measure.as_ms() >= 80 && measure.as_ms() <= 120); - assert!(measure.as_us() >= 80_000 && measure.as_us() <= 120_000); - assert!(measure.as_ns() >= 80_000_000 && measure.as_ns() <= 120_000_000); - assert!( - measure.as_duration() >= Duration::from_millis(90) - && measure.as_duration() <= Duration::from_millis(110) - ); + assert!(measure.as_duration() >= test_duration); } #[test] - fn test_measure_end_as() { - #[track_caller] - fn test_end_as(method: fn(Measure) -> Res, sleep_ms: u64, lower: Res, upper: Res) - where - Res: PartialOrd + Debug, - { - let measure = Measure::start("test"); - sleep(Duration::from_millis(sleep_ms)); - let result = method(measure); - assert!( - result >= lower, - "Result below the expected bound.\n\ - Lower bound: {lower:?}\n\ - Result: {result:?}" - ); - assert!( - result <= upper, - "Result above the expected bound.\n\ - Upper bound: {upper:?}\n\ - Result: {result:?}" - ); - } + fn test_measure_as() { + let test_duration = Duration::from_millis(100); + let measure = Measure { + name: "test", + start: Instant::now(), + duration: test_duration.as_nanos() as u64, + }; - // We have observed failures with margins of 10%, when CI machines are very busy, running - // multiple tests in parallel. As we are not testing the timer functionality itself, it is - // probably OK to increase the margins to 20%. - - test_end_as(Measure::end_as_s, 100, 0.08f32, 0.12f32); - test_end_as(Measure::end_as_ms, 100, 80, 120); - test_end_as(Measure::end_as_us, 100, 80_000, 120_000); - test_end_as(Measure::end_as_ns, 100, 80_000_000, 120_000_000); - test_end_as( - Measure::end_as_duration, - 100, - Duration::from_millis(80), - Duration::from_millis(120), - ); + assert!(f32::abs(measure.as_s() - 0.1f32) <= f32::EPSILON); + assert_eq!(measure.as_ms(), 100); + assert_eq!(measure.as_us(), 100_000); + assert_eq!(measure.as_ns(), 100_000_000); + assert_eq!(measure.as_duration(), test_duration); } #[test] diff --git a/sdk/src/timing.rs b/sdk/src/timing.rs index 376db20238..c5b0172dd7 100644 --- a/sdk/src/timing.rs +++ b/sdk/src/timing.rs @@ -168,4 +168,59 @@ mod test { Duration::from_millis(1000) * ticks_per_slot ); } + + #[test] + fn test_duration_as() { + // zero + let test_zero = Duration::from_nanos(0); + assert_eq!(duration_as_ns(&test_zero), 0); + assert_eq!(duration_as_us(&test_zero), 0); + assert_eq!(duration_as_ms(&test_zero), 0); + assert!((duration_as_s(&test_zero) - 0f32) <= f32::EPSILON); + // min non-zero for each unit + let test_1ns = Duration::from_nanos(1); + assert_eq!(duration_as_ns(&test_1ns), 1); + assert_eq!(duration_as_us(&test_1ns), 0); + assert_eq!(duration_as_ms(&test_1ns), 0); + assert!((duration_as_s(&test_1ns) - 0.000_000_001f32) <= f32::EPSILON); + let test_1ns = Duration::from_micros(1); + assert_eq!(duration_as_ns(&test_1ns), 1_000); + assert_eq!(duration_as_us(&test_1ns), 1); + assert_eq!(duration_as_ms(&test_1ns), 0); + assert!((duration_as_s(&test_1ns) - 0.000_001f32) <= f32::EPSILON); + let test_1ns = Duration::from_millis(1); + assert_eq!(duration_as_ns(&test_1ns), 1_000_000); + assert_eq!(duration_as_us(&test_1ns), 1_000); + assert_eq!(duration_as_ms(&test_1ns), 1); + assert!((duration_as_s(&test_1ns) - 0.001f32) <= f32::EPSILON); + let test_1ns = Duration::from_secs(1); + assert_eq!(duration_as_ns(&test_1ns), 1_000_000_000); + assert_eq!(duration_as_us(&test_1ns), 1_000_000); + assert_eq!(duration_as_ms(&test_1ns), 1_000); + assert!((duration_as_s(&test_1ns) - 1f32) <= f32::EPSILON); + // max without error for each unit (except secs, 'cause if you use floats + // you deserve to get got) + const DUR_MAX_SECS: u64 = Duration::MAX.as_secs(); + const NS_PER_SEC: u64 = 1_000_000_000; + let max_as_ns_secs = DUR_MAX_SECS / NS_PER_SEC; + let max_as_ns_ns = (DUR_MAX_SECS % NS_PER_SEC) as u32; + let max_as_ns = Duration::new(max_as_ns_secs, max_as_ns_ns); + assert_eq!(max_as_ns_secs, 18_446_744_073); + assert_eq!(max_as_ns_ns, 709_551_615); + assert_eq!(duration_as_ns(&max_as_ns), u64::MAX); + const US_PER_SEC: u64 = 1_000_000; + let max_as_us_secs = DUR_MAX_SECS / US_PER_SEC; + let max_as_us_ns = (DUR_MAX_SECS % US_PER_SEC) as u32; + let max_as_us = Duration::new(max_as_us_secs, max_as_us_ns * 1_000); + assert_eq!(max_as_us_secs, 18_446_744_073_709); + assert_eq!(max_as_us_ns, 551_615); + assert_eq!(duration_as_us(&max_as_us), u64::MAX); + const MS_PER_SEC: u64 = 1_000; + let max_as_ms_secs = DUR_MAX_SECS / MS_PER_SEC; + let max_as_ms_ns = (DUR_MAX_SECS % MS_PER_SEC) as u32; + let max_as_ms = Duration::new(max_as_ms_secs, max_as_ms_ns * 1_000_000); + assert_eq!(max_as_ms_secs, 18_446_744_073_709_551); + assert_eq!(max_as_ms_ns, 615); + assert_eq!(duration_as_ms(&max_as_ms), u64::MAX); + } }