From 028644dd82e5fdb02741a6ee6e82a4ba6fdac5d8 Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Tue, 20 Sep 2022 18:25:27 +0200 Subject: [PATCH 1/5] clock: time extent, maker, and associated traits `TimeExtent` is a simple structure that contains base increment (duration), and amount (a multiplier for the base the base increment). The resulting product of the base and the multiplier is the total duration of the time extent. `TimeExtentMaker` is a helper that generates time extents based upon the increment length and the time of the clock, this clock is specialised according to the `test` predicate with the `DefaultClockTimeExtentMaker` type. --- src/protocol/{clock.rs => clock/mod.rs} | 6 +- src/protocol/clock/timeextent.rs | 185 ++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 2 deletions(-) rename src/protocol/{clock.rs => clock/mod.rs} (99%) create mode 100644 src/protocol/clock/timeextent.rs diff --git a/src/protocol/clock.rs b/src/protocol/clock/mod.rs similarity index 99% rename from src/protocol/clock.rs rename to src/protocol/clock/mod.rs index a72f3699e..cab7290e3 100644 --- a/src/protocol/clock.rs +++ b/src/protocol/clock/mod.rs @@ -1,5 +1,5 @@ use std::num::IntErrorKind; -pub use std::time::Duration; +use std::time::Duration; pub type DurationSinceUnixEpoch = Duration; @@ -240,9 +240,11 @@ mod stopped_clock { #[test] fn it_should_get_app_start_time() { - const TIME_AT_WRITING_THIS_TEST: Duration = Duration::new(1662983731, 000022312); + const TIME_AT_WRITING_THIS_TEST: Duration = Duration::new(1662983731, 22312); assert!(get_app_start_time() > TIME_AT_WRITING_THIS_TEST); } } } } + +pub mod timeextent; diff --git a/src/protocol/clock/timeextent.rs b/src/protocol/clock/timeextent.rs new file mode 100644 index 000000000..eb050179e --- /dev/null +++ b/src/protocol/clock/timeextent.rs @@ -0,0 +1,185 @@ +use std::num::{IntErrorKind, TryFromIntError}; +use std::time::Duration; + +use super::{ClockType, StoppedClock, TimeNow, WorkingClock}; + +pub trait Extent: Sized + Default { + type Base; + type Multiplier; + type Product; + + fn new(unit: &Self::Base, count: &Self::Multiplier) -> Self; + + fn add(&self, add: Self::Multiplier) -> Result; + fn sub(&self, sub: Self::Multiplier) -> Result; + + fn total(&self) -> Result, TryFromIntError>; + fn total_next(&self) -> Result, TryFromIntError>; +} + +pub type TimeExtentBase = Duration; +pub type TimeExtentMultiplier = u64; +pub type TimeExtentProduct = TimeExtentBase; + +#[derive(Debug, Default, Hash, PartialEq, Eq)] +pub struct TimeExtent { + pub increment: TimeExtentBase, + pub amount: TimeExtentMultiplier, +} + +impl TimeExtent { + pub const fn from_sec(seconds: u64, amount: &TimeExtentMultiplier) -> Self { + Self { + increment: TimeExtentBase::from_secs(seconds), + amount: *amount, + } + } +} + +impl Extent for TimeExtent { + type Base = TimeExtentBase; + type Multiplier = TimeExtentMultiplier; + type Product = TimeExtentProduct; + + fn new(increment: &Self::Base, amount: &Self::Multiplier) -> Self { + Self { + increment: *increment, + amount: *amount, + } + } + + fn add(&self, add: Self::Multiplier) -> Result { + match self.amount.checked_add(add) { + None => Err(IntErrorKind::PosOverflow), + Some(amount) => Ok(Self { + increment: self.increment, + amount, + }), + } + } + + fn sub(&self, sub: Self::Multiplier) -> Result { + match self.amount.checked_sub(sub) { + None => Err(IntErrorKind::NegOverflow), + Some(amount) => Ok(Self { + increment: self.increment, + amount, + }), + } + } + + fn total(&self) -> Result, TryFromIntError> { + match u32::try_from(self.amount) { + Err(error) => Err(error), + Ok(amount) => Ok(self.increment.checked_mul(amount)), + } + } + + fn total_next(&self) -> Result, TryFromIntError> { + match u32::try_from(self.amount) { + Err(e) => Err(e), + Ok(amount) => match amount.checked_add(1) { + None => Ok(None), + Some(amount) => match self.increment.checked_mul(amount) { + None => Ok(None), + Some(extent) => Ok(Some(extent)), + }, + }, + } + } +} + +pub trait MakeTimeExtent: Sized +where + Clock: TimeNow, +{ + fn now(increment: &TimeExtentBase) -> Option> { + Clock::now() + .as_nanos() + .checked_div((*increment).as_nanos()) + .map(|amount| match TimeExtentMultiplier::try_from(amount) { + Err(error) => Err(error), + Ok(amount) => Ok(TimeExtent::new(increment, &amount)), + }) + } + + fn now_add(increment: &TimeExtentBase, add_time: &Duration) -> Option> { + match Clock::add(add_time) { + None => None, + Some(time) => { + time.as_nanos() + .checked_div(increment.as_nanos()) + .map(|amount| match TimeExtentMultiplier::try_from(amount) { + Err(error) => Err(error), + Ok(amount) => Ok(TimeExtent::new(increment, &amount)), + }) + } + } + } + fn now_sub(increment: &TimeExtentBase, sub_time: &Duration) -> Option> { + match Clock::sub(sub_time) { + None => None, + Some(time) => { + time.as_nanos() + .checked_div(increment.as_nanos()) + .map(|amount| match TimeExtentMultiplier::try_from(amount) { + Err(error) => Err(error), + Ok(amount) => Ok(TimeExtent::new(increment, &amount)), + }) + } + } + } +} + +#[derive(Debug)] +pub struct TimeExtentMaker {} + +pub type WorkingClockTimeExtentMaker = TimeExtentMaker<{ ClockType::WorkingClock as usize }>; +pub type StoppedClockTimeExtentMaker = TimeExtentMaker<{ ClockType::StoppedClock as usize }>; + +impl MakeTimeExtent for WorkingClockTimeExtentMaker {} +impl MakeTimeExtent for StoppedClockTimeExtentMaker {} + +#[cfg(not(test))] +pub type DefaultClockTimeExtentMaker = WorkingClockTimeExtentMaker; + +#[cfg(test)] +pub type DefaultClockTimeExtentMaker = StoppedClockTimeExtentMaker; + +#[cfg(test)] +mod test { + + use std::time::Duration; + + use crate::protocol::clock::timeextent::{DefaultClockTimeExtentMaker, Extent, MakeTimeExtent, TimeExtent}; + use crate::protocol::clock::{DefaultClock, DurationSinceUnixEpoch, StoppedTime}; + + #[test] + fn it_should_get_the_total_duration() { + assert_eq!(TimeExtent::default().total().unwrap().unwrap(), Duration::ZERO); + + assert_eq!( + TimeExtent::from_sec(12, &12).total().unwrap().unwrap(), + Duration::from_secs(144) + ); + assert_eq!( + TimeExtent::from_sec(12, &12).total_next().unwrap().unwrap(), + Duration::from_secs(156) + ); + } + + #[test] + fn it_should_make_the_current_extent() { + assert_eq!( + DefaultClockTimeExtentMaker::now(&Duration::from_secs(2)).unwrap().unwrap(), + TimeExtent::from_sec(2, &0) + ); + + DefaultClock::local_set(&DurationSinceUnixEpoch::from_secs(12387687123)); + + assert_eq!( + DefaultClockTimeExtentMaker::now(&Duration::from_secs(2)).unwrap().unwrap(), + TimeExtent::from_sec(2, &6193843561) + ); + } +} From 0cab30cd2f60d1bf6e2d2d9296a75451f4319d53 Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Wed, 21 Sep 2022 14:48:34 +0200 Subject: [PATCH 2/5] time extent: add tests and some corrections * Write tests for all functions. * Rename `now_add` to `now_after` and `now_sub` to `now_before`. * Rework time extent totals calculations to work with larger numbers. --- src/protocol/clock/timeextent.rs | 437 +++++++++++++++++++++++++++---- 1 file changed, 383 insertions(+), 54 deletions(-) diff --git a/src/protocol/clock/timeextent.rs b/src/protocol/clock/timeextent.rs index eb050179e..dfd00efe7 100644 --- a/src/protocol/clock/timeextent.rs +++ b/src/protocol/clock/timeextent.rs @@ -10,11 +10,11 @@ pub trait Extent: Sized + Default { fn new(unit: &Self::Base, count: &Self::Multiplier) -> Self; - fn add(&self, add: Self::Multiplier) -> Result; - fn sub(&self, sub: Self::Multiplier) -> Result; + fn increase(&self, add: Self::Multiplier) -> Result; + fn decrease(&self, sub: Self::Multiplier) -> Result; - fn total(&self) -> Result, TryFromIntError>; - fn total_next(&self) -> Result, TryFromIntError>; + fn total(&self) -> Option>; + fn total_next(&self) -> Option>; } pub type TimeExtentBase = Duration; @@ -36,6 +36,20 @@ impl TimeExtent { } } +fn checked_duration_from_nanos(time: u128) -> Result { + const NANOS_PER_SEC: u32 = 1_000_000_000; + + let secs = time.div_euclid(NANOS_PER_SEC as u128); + let nanos = time.rem_euclid(NANOS_PER_SEC as u128); + + assert!(nanos < NANOS_PER_SEC as u128); + + match u64::try_from(secs) { + Err(error) => Err(error), + Ok(secs) => Ok(Duration::new(secs, nanos.try_into().unwrap())), + } +} + impl Extent for TimeExtent { type Base = TimeExtentBase; type Multiplier = TimeExtentMultiplier; @@ -48,7 +62,7 @@ impl Extent for TimeExtent { } } - fn add(&self, add: Self::Multiplier) -> Result { + fn increase(&self, add: Self::Multiplier) -> Result { match self.amount.checked_add(add) { None => Err(IntErrorKind::PosOverflow), Some(amount) => Ok(Self { @@ -58,7 +72,7 @@ impl Extent for TimeExtent { } } - fn sub(&self, sub: Self::Multiplier) -> Result { + fn decrease(&self, sub: Self::Multiplier) -> Result { match self.amount.checked_sub(sub) { None => Err(IntErrorKind::NegOverflow), Some(amount) => Ok(Self { @@ -68,24 +82,18 @@ impl Extent for TimeExtent { } } - fn total(&self) -> Result, TryFromIntError> { - match u32::try_from(self.amount) { - Err(error) => Err(error), - Ok(amount) => Ok(self.increment.checked_mul(amount)), - } + fn total(&self) -> Option> { + self.increment + .as_nanos() + .checked_mul(self.amount as u128) + .map(checked_duration_from_nanos) } - fn total_next(&self) -> Result, TryFromIntError> { - match u32::try_from(self.amount) { - Err(e) => Err(e), - Ok(amount) => match amount.checked_add(1) { - None => Ok(None), - Some(amount) => match self.increment.checked_mul(amount) { - None => Ok(None), - Some(extent) => Ok(Some(extent)), - }, - }, - } + fn total_next(&self) -> Option> { + self.increment + .as_nanos() + .checked_mul((self.amount as u128) + 1) + .map(checked_duration_from_nanos) } } @@ -103,7 +111,7 @@ where }) } - fn now_add(increment: &TimeExtentBase, add_time: &Duration) -> Option> { + fn now_after(increment: &TimeExtentBase, add_time: &Duration) -> Option> { match Clock::add(add_time) { None => None, Some(time) => { @@ -116,7 +124,7 @@ where } } } - fn now_sub(increment: &TimeExtentBase, sub_time: &Duration) -> Option> { + fn now_before(increment: &TimeExtentBase, sub_time: &Duration) -> Option> { match Clock::sub(sub_time) { None => None, Some(time) => { @@ -149,37 +157,358 @@ pub type DefaultClockTimeExtentMaker = StoppedClockTimeExtentMaker; #[cfg(test)] mod test { - use std::time::Duration; - - use crate::protocol::clock::timeextent::{DefaultClockTimeExtentMaker, Extent, MakeTimeExtent, TimeExtent}; + use crate::protocol::clock::timeextent::{ + checked_duration_from_nanos, DefaultClockTimeExtentMaker, Extent, MakeTimeExtent, TimeExtent, TimeExtentBase, + TimeExtentProduct, + }; use crate::protocol::clock::{DefaultClock, DurationSinceUnixEpoch, StoppedTime}; - #[test] - fn it_should_get_the_total_duration() { - assert_eq!(TimeExtent::default().total().unwrap().unwrap(), Duration::ZERO); - - assert_eq!( - TimeExtent::from_sec(12, &12).total().unwrap().unwrap(), - Duration::from_secs(144) - ); - assert_eq!( - TimeExtent::from_sec(12, &12).total_next().unwrap().unwrap(), - Duration::from_secs(156) - ); - } - - #[test] - fn it_should_make_the_current_extent() { - assert_eq!( - DefaultClockTimeExtentMaker::now(&Duration::from_secs(2)).unwrap().unwrap(), - TimeExtent::from_sec(2, &0) - ); - - DefaultClock::local_set(&DurationSinceUnixEpoch::from_secs(12387687123)); - - assert_eq!( - DefaultClockTimeExtentMaker::now(&Duration::from_secs(2)).unwrap().unwrap(), - TimeExtent::from_sec(2, &6193843561) - ); + const TIME_EXTENT_VAL: TimeExtent = TimeExtent::from_sec(2, &239812388723); + + mod fn_checked_duration_from_nanos { + use std::time::Duration; + + use super::*; + + const NANOS_PER_SEC: u32 = 1_000_000_000; + + #[test] + fn it_should_return_a_duration() { + assert_eq!(checked_duration_from_nanos(0).unwrap(), Duration::from_micros(0)); + assert_eq!( + checked_duration_from_nanos(1232143214343432).unwrap(), + Duration::from_nanos(1232143214343432) + ); + assert_eq!( + checked_duration_from_nanos(u64::MAX as u128).unwrap(), + Duration::from_nanos(u64::MAX) + ); + assert_eq!( + checked_duration_from_nanos(TIME_EXTENT_VAL.amount as u128 * NANOS_PER_SEC as u128).unwrap(), + Duration::from_secs(TIME_EXTENT_VAL.amount) + ); + } + + #[test] + fn it_should_return_tryfrom_int_error() { + assert_eq!( + checked_duration_from_nanos(u128::MAX).unwrap_err(), + u64::try_from(u128::MAX).unwrap_err() + ); + } + } + + mod time_extent_from_sec { + use super::*; + + #[test] + fn it_should_make_time_extent() { + assert_eq!(TIME_EXTENT_VAL.increment, TimeExtentBase::from_secs(2)); + assert_eq!(TIME_EXTENT_VAL.amount, 239812388723); + } + } + + mod time_extent_default { + use super::*; + + #[test] + fn it_should_make_time_extent() { + let time_extent_default = TimeExtent::default(); + assert_eq!(time_extent_default.increment, TimeExtentBase::ZERO); + assert_eq!(time_extent_default.amount, 0); + } + } + + mod time_extent_new { + use super::*; + + #[test] + fn it_should_make_time_extent() { + let time_extent = TimeExtent::new(&TimeExtentBase::from_millis(2), &TIME_EXTENT_VAL.amount); + assert_eq!(time_extent.increment, TimeExtentBase::from_millis(2)); + assert_eq!(time_extent.amount, TIME_EXTENT_VAL.amount); + } + } + + mod time_extent_increase { + use std::num::IntErrorKind; + + use super::*; + + #[test] + fn it_should_return_increased() { + let time_extent_default = TimeExtent::default(); + let time_extent = TimeExtent::new(&TimeExtentBase::from_millis(2), &TIME_EXTENT_VAL.amount); + + let time_extent_default_increase = TimeExtent { + increment: TimeExtentBase::ZERO, + amount: 50, + }; + let time_extent_increase = TimeExtent { + increment: TimeExtentBase::from_millis(2), + amount: TIME_EXTENT_VAL.amount + 50, + }; + let time_extent_from_sec_increase = TimeExtent { + increment: TIME_EXTENT_VAL.increment, + amount: TIME_EXTENT_VAL.amount + 50, + }; + + assert_eq!(time_extent_default.increase(50).unwrap(), time_extent_default_increase); + assert_eq!(time_extent.increase(50).unwrap(), time_extent_increase); + assert_eq!(TIME_EXTENT_VAL.increase(50).unwrap(), time_extent_from_sec_increase); + } + + #[test] + fn it_should_postive_overflow() { + assert_eq!(TIME_EXTENT_VAL.increase(u64::MAX), Err(IntErrorKind::PosOverflow)); + } + } + + mod time_extent_decrease { + use std::num::IntErrorKind; + + use super::*; + + #[test] + fn it_should_return_decreased() { + let time_extent_default = TimeExtent::default(); + let time_extent = TimeExtent::new(&TimeExtentBase::from_millis(2), &TIME_EXTENT_VAL.amount); + + let time_extent_default_decrease = TimeExtent { + increment: TimeExtentBase::ZERO, + amount: 0, + }; + let time_extent_decrease = TimeExtent { + increment: TimeExtentBase::from_millis(2), + amount: TIME_EXTENT_VAL.amount - 50, + }; + let time_extent_from_sec_decrease = TimeExtent { + increment: TIME_EXTENT_VAL.increment, + amount: TIME_EXTENT_VAL.amount - 50, + }; + + assert_eq!(time_extent_default.decrease(0).unwrap(), time_extent_default_decrease); + assert_eq!(time_extent.decrease(50).unwrap(), time_extent_decrease); + assert_eq!(TIME_EXTENT_VAL.decrease(50).unwrap(), time_extent_from_sec_decrease); + } + + #[test] + fn it_should_return_an_negitive_overflow() { + assert_eq!(TIME_EXTENT_VAL.decrease(u64::MAX), Err(IntErrorKind::NegOverflow)); + } + } + + mod time_extent_total { + use super::*; + + #[test] + fn it_should_return_total() { + let time_extent_default = TimeExtent::default(); + let time_extent = TimeExtent::new(&TimeExtentBase::from_millis(2), &(TIME_EXTENT_VAL.amount / 1000)); + + assert_eq!(time_extent_default.total().unwrap().unwrap(), TimeExtentProduct::ZERO); + assert_eq!( + time_extent.total().unwrap().unwrap(), + TimeExtentProduct::new(479624, 776000000) + ); + assert_eq!( + TIME_EXTENT_VAL.total().unwrap().unwrap(), + TimeExtentProduct::from_secs(TIME_EXTENT_VAL.increment.as_secs() * TIME_EXTENT_VAL.amount) + ); + } + + #[test] + fn it_should_return_none() { + let time_extent_max = TimeExtent { + increment: TimeExtentBase::MAX, + amount: u64::MAX as u64, + }; + assert_eq!(time_extent_max.total(), None); + } + + #[test] + fn it_should_return_tryfrom_int_error() { + let time_extent_max = TimeExtent { + increment: TimeExtentBase::MAX, + amount: 2, + }; + assert_eq!( + time_extent_max.total().unwrap().unwrap_err(), + u64::try_from(u128::MAX).unwrap_err() + ); + } + } + + mod time_extent_total_next { + use super::*; + + #[test] + fn it_should_get_the_time_extent_total_next() { + let time_extent_default = TimeExtent::default(); + let time_extent = TimeExtent::new(&TimeExtentBase::from_millis(2), &TIME_EXTENT_VAL.amount); + + assert_eq!( + time_extent_default.total_next().unwrap().unwrap(), + TimeExtentProduct::from_secs(0) + ); + assert_eq!( + time_extent.total_next().unwrap().unwrap(), + TimeExtentProduct::new(479624777, 448000000) + ); + assert_eq!( + TIME_EXTENT_VAL.total_next().unwrap().unwrap(), + TimeExtentProduct::from_secs(TIME_EXTENT_VAL.increment.as_secs() * (TIME_EXTENT_VAL.amount + 1)) + ); + } + + #[test] + fn it_should_return_none() { + let time_extent_max = TimeExtent { + increment: TimeExtentBase::MAX, + amount: u64::MAX as u64, + }; + assert_eq!(time_extent_max.total_next(), None); + } + + #[test] + fn it_should_return_tryfrom_int_error() { + let time_extent_max = TimeExtent { + increment: TimeExtentBase::MAX, + amount: 2, + }; + assert_eq!( + time_extent_max.total_next().unwrap().unwrap_err(), + u64::try_from(u128::MAX).unwrap_err() + ); + } + } + + mod make_time_extent_now { + use super::*; + + #[test] + fn it_should_return_a_time_extent() { + assert_eq!( + DefaultClockTimeExtentMaker::now(&TIME_EXTENT_VAL.increment).unwrap().unwrap(), + TimeExtent { + increment: TIME_EXTENT_VAL.increment, + amount: 0 + } + ); + + DefaultClock::local_set(&DurationSinceUnixEpoch::from_secs(TIME_EXTENT_VAL.amount * 2)); + + assert_eq!( + DefaultClockTimeExtentMaker::now(&TIME_EXTENT_VAL.increment).unwrap().unwrap(), + TIME_EXTENT_VAL + ); + } + + #[test] + fn it_should_return_none() { + assert_eq!(DefaultClockTimeExtentMaker::now(&TimeExtentBase::ZERO), None); + } + + #[test] + fn it_should_return_tryfrom_int_error() { + DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); + assert_eq!( + DefaultClockTimeExtentMaker::now(&TimeExtentBase::from_millis(1)) + .unwrap() + .unwrap_err(), + u64::try_from(u128::MAX).unwrap_err() + ); + } + } + + mod make_time_extent_now_after { + use std::time::Duration; + + use super::*; + + #[test] + fn it_should_return_a_time_extent() { + assert_eq!( + DefaultClockTimeExtentMaker::now_after( + &TIME_EXTENT_VAL.increment, + &Duration::from_secs(TIME_EXTENT_VAL.amount * 2) + ) + .unwrap() + .unwrap(), + TIME_EXTENT_VAL + ); + } + + #[test] + fn it_should_return_none() { + assert_eq!( + DefaultClockTimeExtentMaker::now_after(&TimeExtentBase::ZERO, &Duration::ZERO), + None + ); + + DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); + assert_eq!( + DefaultClockTimeExtentMaker::now_after(&TimeExtentBase::ZERO, &Duration::MAX), + None + ); + } + + #[test] + fn it_should_return_tryfrom_int_error() { + DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); + assert_eq!( + DefaultClockTimeExtentMaker::now_after(&TimeExtentBase::from_millis(1), &Duration::ZERO) + .unwrap() + .unwrap_err(), + u64::try_from(u128::MAX).unwrap_err() + ); + } + } + mod make_time_extent_now_before { + use std::time::Duration; + + use super::*; + + #[test] + fn it_should_return_a_time_extent() { + DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); + + assert_eq!( + DefaultClockTimeExtentMaker::now_before( + &TimeExtentBase::from_secs(u32::MAX as u64), + &Duration::from_secs(u32::MAX as u64) + ) + .unwrap() + .unwrap(), + TimeExtent { + increment: TimeExtentBase::from_secs(u32::MAX as u64), + amount: 4294967296 + } + ); + } + + #[test] + fn it_should_return_none() { + assert_eq!( + DefaultClockTimeExtentMaker::now_before(&TimeExtentBase::ZERO, &Duration::ZERO), + None + ); + + assert_eq!( + DefaultClockTimeExtentMaker::now_before(&TimeExtentBase::ZERO, &Duration::MAX), + None + ); + } + + #[test] + fn it_should_return_tryfrom_int_error() { + DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); + assert_eq!( + DefaultClockTimeExtentMaker::now_before(&TimeExtentBase::from_millis(1), &Duration::ZERO) + .unwrap() + .unwrap_err(), + u64::try_from(u128::MAX).unwrap_err() + ); + } } } From 8653f9a509431433c4aabd004cdf419ffd0ef62d Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Wed, 21 Sep 2022 15:02:11 +0200 Subject: [PATCH 3/5] time extent: rename `TimeExtentMaker` for clarity Rename: from `DefaultClockTimeExtentMaker` to `DefaultTimeExtentMaker`, and the associated types. Co-authored-by: Jose Celano --- src/protocol/clock/timeextent.rs | 48 ++++++++++++++------------------ 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/src/protocol/clock/timeextent.rs b/src/protocol/clock/timeextent.rs index dfd00efe7..0356b7f39 100644 --- a/src/protocol/clock/timeextent.rs +++ b/src/protocol/clock/timeextent.rs @@ -142,23 +142,23 @@ where #[derive(Debug)] pub struct TimeExtentMaker {} -pub type WorkingClockTimeExtentMaker = TimeExtentMaker<{ ClockType::WorkingClock as usize }>; -pub type StoppedClockTimeExtentMaker = TimeExtentMaker<{ ClockType::StoppedClock as usize }>; +pub type WorkingTimeExtentMaker = TimeExtentMaker<{ ClockType::WorkingClock as usize }>; +pub type StoppedTimeExtentMaker = TimeExtentMaker<{ ClockType::StoppedClock as usize }>; -impl MakeTimeExtent for WorkingClockTimeExtentMaker {} -impl MakeTimeExtent for StoppedClockTimeExtentMaker {} +impl MakeTimeExtent for WorkingTimeExtentMaker {} +impl MakeTimeExtent for StoppedTimeExtentMaker {} #[cfg(not(test))] -pub type DefaultClockTimeExtentMaker = WorkingClockTimeExtentMaker; +pub type DefaultTimeExtentMaker = WorkingTimeExtentMaker; #[cfg(test)] -pub type DefaultClockTimeExtentMaker = StoppedClockTimeExtentMaker; +pub type DefaultTimeExtentMaker = StoppedTimeExtentMaker; #[cfg(test)] mod test { use crate::protocol::clock::timeextent::{ - checked_duration_from_nanos, DefaultClockTimeExtentMaker, Extent, MakeTimeExtent, TimeExtent, TimeExtentBase, + checked_duration_from_nanos, DefaultTimeExtentMaker, Extent, MakeTimeExtent, TimeExtent, TimeExtentBase, TimeExtentProduct, }; use crate::protocol::clock::{DefaultClock, DurationSinceUnixEpoch, StoppedTime}; @@ -389,7 +389,7 @@ mod test { #[test] fn it_should_return_a_time_extent() { assert_eq!( - DefaultClockTimeExtentMaker::now(&TIME_EXTENT_VAL.increment).unwrap().unwrap(), + DefaultTimeExtentMaker::now(&TIME_EXTENT_VAL.increment).unwrap().unwrap(), TimeExtent { increment: TIME_EXTENT_VAL.increment, amount: 0 @@ -399,21 +399,21 @@ mod test { DefaultClock::local_set(&DurationSinceUnixEpoch::from_secs(TIME_EXTENT_VAL.amount * 2)); assert_eq!( - DefaultClockTimeExtentMaker::now(&TIME_EXTENT_VAL.increment).unwrap().unwrap(), + DefaultTimeExtentMaker::now(&TIME_EXTENT_VAL.increment).unwrap().unwrap(), TIME_EXTENT_VAL ); } #[test] fn it_should_return_none() { - assert_eq!(DefaultClockTimeExtentMaker::now(&TimeExtentBase::ZERO), None); + assert_eq!(DefaultTimeExtentMaker::now(&TimeExtentBase::ZERO), None); } #[test] fn it_should_return_tryfrom_int_error() { DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); assert_eq!( - DefaultClockTimeExtentMaker::now(&TimeExtentBase::from_millis(1)) + DefaultTimeExtentMaker::now(&TimeExtentBase::from_millis(1)) .unwrap() .unwrap_err(), u64::try_from(u128::MAX).unwrap_err() @@ -429,12 +429,9 @@ mod test { #[test] fn it_should_return_a_time_extent() { assert_eq!( - DefaultClockTimeExtentMaker::now_after( - &TIME_EXTENT_VAL.increment, - &Duration::from_secs(TIME_EXTENT_VAL.amount * 2) - ) - .unwrap() - .unwrap(), + DefaultTimeExtentMaker::now_after(&TIME_EXTENT_VAL.increment, &Duration::from_secs(TIME_EXTENT_VAL.amount * 2)) + .unwrap() + .unwrap(), TIME_EXTENT_VAL ); } @@ -442,22 +439,19 @@ mod test { #[test] fn it_should_return_none() { assert_eq!( - DefaultClockTimeExtentMaker::now_after(&TimeExtentBase::ZERO, &Duration::ZERO), + DefaultTimeExtentMaker::now_after(&TimeExtentBase::ZERO, &Duration::ZERO), None ); DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); - assert_eq!( - DefaultClockTimeExtentMaker::now_after(&TimeExtentBase::ZERO, &Duration::MAX), - None - ); + assert_eq!(DefaultTimeExtentMaker::now_after(&TimeExtentBase::ZERO, &Duration::MAX), None); } #[test] fn it_should_return_tryfrom_int_error() { DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); assert_eq!( - DefaultClockTimeExtentMaker::now_after(&TimeExtentBase::from_millis(1), &Duration::ZERO) + DefaultTimeExtentMaker::now_after(&TimeExtentBase::from_millis(1), &Duration::ZERO) .unwrap() .unwrap_err(), u64::try_from(u128::MAX).unwrap_err() @@ -474,7 +468,7 @@ mod test { DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); assert_eq!( - DefaultClockTimeExtentMaker::now_before( + DefaultTimeExtentMaker::now_before( &TimeExtentBase::from_secs(u32::MAX as u64), &Duration::from_secs(u32::MAX as u64) ) @@ -490,12 +484,12 @@ mod test { #[test] fn it_should_return_none() { assert_eq!( - DefaultClockTimeExtentMaker::now_before(&TimeExtentBase::ZERO, &Duration::ZERO), + DefaultTimeExtentMaker::now_before(&TimeExtentBase::ZERO, &Duration::ZERO), None ); assert_eq!( - DefaultClockTimeExtentMaker::now_before(&TimeExtentBase::ZERO, &Duration::MAX), + DefaultTimeExtentMaker::now_before(&TimeExtentBase::ZERO, &Duration::MAX), None ); } @@ -504,7 +498,7 @@ mod test { fn it_should_return_tryfrom_int_error() { DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); assert_eq!( - DefaultClockTimeExtentMaker::now_before(&TimeExtentBase::from_millis(1), &Duration::ZERO) + DefaultTimeExtentMaker::now_before(&TimeExtentBase::from_millis(1), &Duration::ZERO) .unwrap() .unwrap_err(), u64::try_from(u128::MAX).unwrap_err() From 3d743edec410f7d0e96db37d66e01cab8b248ec4 Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Wed, 21 Sep 2022 15:28:32 +0200 Subject: [PATCH 4/5] time extent: use snake_case for module name Rename: from timeextent to time_extent. Co-authored-by: Jose Celano --- src/protocol/clock/mod.rs | 2 +- src/protocol/clock/{timeextent.rs => time_extent.rs} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/protocol/clock/{timeextent.rs => time_extent.rs} (99%) diff --git a/src/protocol/clock/mod.rs b/src/protocol/clock/mod.rs index cab7290e3..4e15950e6 100644 --- a/src/protocol/clock/mod.rs +++ b/src/protocol/clock/mod.rs @@ -247,4 +247,4 @@ mod stopped_clock { } } -pub mod timeextent; +pub mod time_extent; diff --git a/src/protocol/clock/timeextent.rs b/src/protocol/clock/time_extent.rs similarity index 99% rename from src/protocol/clock/timeextent.rs rename to src/protocol/clock/time_extent.rs index 0356b7f39..85b5257ad 100644 --- a/src/protocol/clock/timeextent.rs +++ b/src/protocol/clock/time_extent.rs @@ -157,7 +157,7 @@ pub type DefaultTimeExtentMaker = StoppedTimeExtentMaker; #[cfg(test)] mod test { - use crate::protocol::clock::timeextent::{ + use crate::protocol::clock::time_extent::{ checked_duration_from_nanos, DefaultTimeExtentMaker, Extent, MakeTimeExtent, TimeExtent, TimeExtentBase, TimeExtentProduct, }; From e785a7fd8e0d0a393b1d312d07178ebef43dda25 Mon Sep 17 00:00:00 2001 From: Cameron Garnham Date: Wed, 21 Sep 2022 18:08:13 +0200 Subject: [PATCH 5/5] time extent: overhaul tests naming scheme --- src/protocol/clock/time_extent.rs | 558 ++++++++++++++++-------------- 1 file changed, 302 insertions(+), 256 deletions(-) diff --git a/src/protocol/clock/time_extent.rs b/src/protocol/clock/time_extent.rs index 85b5257ad..d0713645b 100644 --- a/src/protocol/clock/time_extent.rs +++ b/src/protocol/clock/time_extent.rs @@ -27,6 +27,15 @@ pub struct TimeExtent { pub amount: TimeExtentMultiplier, } +pub const ZERO: TimeExtent = TimeExtent { + increment: TimeExtentBase::ZERO, + amount: TimeExtentMultiplier::MIN, +}; +pub const MAX: TimeExtent = TimeExtent { + increment: TimeExtentBase::MAX, + amount: TimeExtentMultiplier::MAX, +}; + impl TimeExtent { pub const fn from_sec(seconds: u64, amount: &TimeExtentMultiplier) -> Self { Self { @@ -159,7 +168,7 @@ mod test { use crate::protocol::clock::time_extent::{ checked_duration_from_nanos, DefaultTimeExtentMaker, Extent, MakeTimeExtent, TimeExtent, TimeExtentBase, - TimeExtentProduct, + TimeExtentMultiplier, TimeExtentProduct, MAX, ZERO, }; use crate::protocol::clock::{DefaultClock, DurationSinceUnixEpoch, StoppedTime}; @@ -173,8 +182,12 @@ mod test { const NANOS_PER_SEC: u32 = 1_000_000_000; #[test] - fn it_should_return_a_duration() { - assert_eq!(checked_duration_from_nanos(0).unwrap(), Duration::from_micros(0)); + fn it_should_give_zero_for_zero_input() { + assert_eq!(checked_duration_from_nanos(0).unwrap(), Duration::ZERO); + } + + #[test] + fn it_should_be_the_same_as_duration_implementation_for_u64_numbers() { assert_eq!( checked_duration_from_nanos(1232143214343432).unwrap(), Duration::from_nanos(1232143214343432) @@ -183,6 +196,10 @@ mod test { checked_duration_from_nanos(u64::MAX as u128).unwrap(), Duration::from_nanos(u64::MAX) ); + } + + #[test] + fn it_should_work_for_some_numbers_larger_than_u64() { assert_eq!( checked_duration_from_nanos(TIME_EXTENT_VAL.amount as u128 * NANOS_PER_SEC as u128).unwrap(), Duration::from_secs(TIME_EXTENT_VAL.amount) @@ -190,7 +207,7 @@ mod test { } #[test] - fn it_should_return_tryfrom_int_error() { + fn it_should_fail_for_numbers_that_are_too_large() { assert_eq!( checked_duration_from_nanos(u128::MAX).unwrap_err(), u64::try_from(u128::MAX).unwrap_err() @@ -198,311 +215,340 @@ mod test { } } - mod time_extent_from_sec { + mod time_extent { use super::*; - #[test] - fn it_should_make_time_extent() { - assert_eq!(TIME_EXTENT_VAL.increment, TimeExtentBase::from_secs(2)); - assert_eq!(TIME_EXTENT_VAL.amount, 239812388723); - } - } + mod fn_default { - mod time_extent_default { - use super::*; + use super::*; - #[test] - fn it_should_make_time_extent() { - let time_extent_default = TimeExtent::default(); - assert_eq!(time_extent_default.increment, TimeExtentBase::ZERO); - assert_eq!(time_extent_default.amount, 0); + #[test] + fn it_should_default_initialize_to_zero() { + assert_eq!(TimeExtent::default(), ZERO); + } } - } - mod time_extent_new { - use super::*; + mod fn_from_sec { + use super::*; - #[test] - fn it_should_make_time_extent() { - let time_extent = TimeExtent::new(&TimeExtentBase::from_millis(2), &TIME_EXTENT_VAL.amount); - assert_eq!(time_extent.increment, TimeExtentBase::from_millis(2)); - assert_eq!(time_extent.amount, TIME_EXTENT_VAL.amount); + #[test] + fn it_should_make_empty_for_zero() { + assert_eq!(TimeExtent::from_sec(u64::MIN, &TimeExtentMultiplier::MIN), ZERO); + } + #[test] + fn it_should_make_from_seconds() { + assert_eq!( + TimeExtent::from_sec(TIME_EXTENT_VAL.increment.as_secs(), &TIME_EXTENT_VAL.amount), + TIME_EXTENT_VAL + ); + } } - } - mod time_extent_increase { - use std::num::IntErrorKind; + mod fn_new { + use super::*; - use super::*; + #[test] + fn it_should_make_empty_for_zero() { + assert_eq!(TimeExtent::new(&TimeExtentBase::ZERO, &TimeExtentMultiplier::MIN), ZERO); + } - #[test] - fn it_should_return_increased() { - let time_extent_default = TimeExtent::default(); - let time_extent = TimeExtent::new(&TimeExtentBase::from_millis(2), &TIME_EXTENT_VAL.amount); - - let time_extent_default_increase = TimeExtent { - increment: TimeExtentBase::ZERO, - amount: 50, - }; - let time_extent_increase = TimeExtent { - increment: TimeExtentBase::from_millis(2), - amount: TIME_EXTENT_VAL.amount + 50, - }; - let time_extent_from_sec_increase = TimeExtent { - increment: TIME_EXTENT_VAL.increment, - amount: TIME_EXTENT_VAL.amount + 50, - }; - - assert_eq!(time_extent_default.increase(50).unwrap(), time_extent_default_increase); - assert_eq!(time_extent.increase(50).unwrap(), time_extent_increase); - assert_eq!(TIME_EXTENT_VAL.increase(50).unwrap(), time_extent_from_sec_increase); + #[test] + fn it_should_make_new() { + assert_eq!( + TimeExtent::new(&TimeExtentBase::from_millis(2), &TIME_EXTENT_VAL.amount), + TimeExtent { + increment: TimeExtentBase::from_millis(2), + amount: TIME_EXTENT_VAL.amount + } + ); + } } - #[test] - fn it_should_postive_overflow() { - assert_eq!(TIME_EXTENT_VAL.increase(u64::MAX), Err(IntErrorKind::PosOverflow)); - } - } + mod fn_increase { + use std::num::IntErrorKind; - mod time_extent_decrease { - use std::num::IntErrorKind; + use super::*; - use super::*; + #[test] + fn it_should_not_increase_for_zero() { + assert_eq!(ZERO.increase(0).unwrap(), ZERO); + } - #[test] - fn it_should_return_decreased() { - let time_extent_default = TimeExtent::default(); - let time_extent = TimeExtent::new(&TimeExtentBase::from_millis(2), &TIME_EXTENT_VAL.amount); - - let time_extent_default_decrease = TimeExtent { - increment: TimeExtentBase::ZERO, - amount: 0, - }; - let time_extent_decrease = TimeExtent { - increment: TimeExtentBase::from_millis(2), - amount: TIME_EXTENT_VAL.amount - 50, - }; - let time_extent_from_sec_decrease = TimeExtent { - increment: TIME_EXTENT_VAL.increment, - amount: TIME_EXTENT_VAL.amount - 50, - }; - - assert_eq!(time_extent_default.decrease(0).unwrap(), time_extent_default_decrease); - assert_eq!(time_extent.decrease(50).unwrap(), time_extent_decrease); - assert_eq!(TIME_EXTENT_VAL.decrease(50).unwrap(), time_extent_from_sec_decrease); - } + #[test] + fn it_should_increase() { + assert_eq!( + TIME_EXTENT_VAL.increase(50).unwrap(), + TimeExtent { + increment: TIME_EXTENT_VAL.increment, + amount: TIME_EXTENT_VAL.amount + 50, + } + ); + } - #[test] - fn it_should_return_an_negitive_overflow() { - assert_eq!(TIME_EXTENT_VAL.decrease(u64::MAX), Err(IntErrorKind::NegOverflow)); + #[test] + fn it_should_fail_when_attempting_to_increase_beyond_bounds() { + assert_eq!(TIME_EXTENT_VAL.increase(u64::MAX), Err(IntErrorKind::PosOverflow)); + } } - } - mod time_extent_total { - use super::*; + mod fn_decrease { + use std::num::IntErrorKind; - #[test] - fn it_should_return_total() { - let time_extent_default = TimeExtent::default(); - let time_extent = TimeExtent::new(&TimeExtentBase::from_millis(2), &(TIME_EXTENT_VAL.amount / 1000)); + use super::*; - assert_eq!(time_extent_default.total().unwrap().unwrap(), TimeExtentProduct::ZERO); - assert_eq!( - time_extent.total().unwrap().unwrap(), - TimeExtentProduct::new(479624, 776000000) - ); - assert_eq!( - TIME_EXTENT_VAL.total().unwrap().unwrap(), - TimeExtentProduct::from_secs(TIME_EXTENT_VAL.increment.as_secs() * TIME_EXTENT_VAL.amount) - ); - } + #[test] + fn it_should_not_decrease_for_zero() { + assert_eq!(ZERO.decrease(0).unwrap(), ZERO); + } - #[test] - fn it_should_return_none() { - let time_extent_max = TimeExtent { - increment: TimeExtentBase::MAX, - amount: u64::MAX as u64, - }; - assert_eq!(time_extent_max.total(), None); - } + #[test] + fn it_should_decrease() { + assert_eq!( + TIME_EXTENT_VAL.decrease(50).unwrap(), + TimeExtent { + increment: TIME_EXTENT_VAL.increment, + amount: TIME_EXTENT_VAL.amount - 50, + } + ); + } - #[test] - fn it_should_return_tryfrom_int_error() { - let time_extent_max = TimeExtent { - increment: TimeExtentBase::MAX, - amount: 2, - }; - assert_eq!( - time_extent_max.total().unwrap().unwrap_err(), - u64::try_from(u128::MAX).unwrap_err() - ); + #[test] + fn it_should_fail_when_attempting_to_decrease_beyond_bounds() { + assert_eq!(TIME_EXTENT_VAL.decrease(u64::MAX), Err(IntErrorKind::NegOverflow)); + } } - } - mod time_extent_total_next { - use super::*; + mod fn_total { + use super::*; - #[test] - fn it_should_get_the_time_extent_total_next() { - let time_extent_default = TimeExtent::default(); - let time_extent = TimeExtent::new(&TimeExtentBase::from_millis(2), &TIME_EXTENT_VAL.amount); + #[test] + fn it_should_be_zero_for_zero() { + assert_eq!(ZERO.total().unwrap().unwrap(), TimeExtentProduct::ZERO); + } - assert_eq!( - time_extent_default.total_next().unwrap().unwrap(), - TimeExtentProduct::from_secs(0) - ); - assert_eq!( - time_extent.total_next().unwrap().unwrap(), - TimeExtentProduct::new(479624777, 448000000) - ); - assert_eq!( - TIME_EXTENT_VAL.total_next().unwrap().unwrap(), - TimeExtentProduct::from_secs(TIME_EXTENT_VAL.increment.as_secs() * (TIME_EXTENT_VAL.amount + 1)) - ); - } + #[test] + fn it_should_give_a_total() { + assert_eq!( + TIME_EXTENT_VAL.total().unwrap().unwrap(), + TimeExtentProduct::from_secs(TIME_EXTENT_VAL.increment.as_secs() * TIME_EXTENT_VAL.amount) + ); + + assert_eq!( + TimeExtent::new(&TimeExtentBase::from_millis(2), &(TIME_EXTENT_VAL.amount * 1000)) + .total() + .unwrap() + .unwrap(), + TimeExtentProduct::from_secs(TIME_EXTENT_VAL.increment.as_secs() * TIME_EXTENT_VAL.amount) + ); + + assert_eq!( + TimeExtent::new(&TimeExtentBase::from_secs(1), &(u64::MAX)) + .total() + .unwrap() + .unwrap(), + TimeExtentProduct::from_secs(u64::MAX) + ); + } - #[test] - fn it_should_return_none() { - let time_extent_max = TimeExtent { - increment: TimeExtentBase::MAX, - amount: u64::MAX as u64, - }; - assert_eq!(time_extent_max.total_next(), None); - } + #[test] + fn it_should_fail_when_too_large() { + assert_eq!(MAX.total(), None); + } - #[test] - fn it_should_return_tryfrom_int_error() { - let time_extent_max = TimeExtent { - increment: TimeExtentBase::MAX, - amount: 2, - }; - assert_eq!( - time_extent_max.total_next().unwrap().unwrap_err(), - u64::try_from(u128::MAX).unwrap_err() - ); + #[test] + fn it_should_fail_when_product_is_too_large() { + let time_extent = TimeExtent { + increment: MAX.increment, + amount: 2, + }; + assert_eq!( + time_extent.total().unwrap().unwrap_err(), + u64::try_from(u128::MAX).unwrap_err() + ); + } } - } - mod make_time_extent_now { - use super::*; + mod fn_total_next { + use super::*; - #[test] - fn it_should_return_a_time_extent() { - assert_eq!( - DefaultTimeExtentMaker::now(&TIME_EXTENT_VAL.increment).unwrap().unwrap(), - TimeExtent { - increment: TIME_EXTENT_VAL.increment, - amount: 0 - } - ); - - DefaultClock::local_set(&DurationSinceUnixEpoch::from_secs(TIME_EXTENT_VAL.amount * 2)); + #[test] + fn it_should_be_zero_for_zero() { + assert_eq!(ZERO.total_next().unwrap().unwrap(), TimeExtentProduct::ZERO); + } - assert_eq!( - DefaultTimeExtentMaker::now(&TIME_EXTENT_VAL.increment).unwrap().unwrap(), - TIME_EXTENT_VAL - ); - } + #[test] + fn it_should_give_a_total() { + assert_eq!( + TIME_EXTENT_VAL.total_next().unwrap().unwrap(), + TimeExtentProduct::from_secs(TIME_EXTENT_VAL.increment.as_secs() * (TIME_EXTENT_VAL.amount + 1)) + ); + + assert_eq!( + TimeExtent::new(&TimeExtentBase::from_millis(2), &(TIME_EXTENT_VAL.amount * 1000)) + .total_next() + .unwrap() + .unwrap(), + TimeExtentProduct::new( + TIME_EXTENT_VAL.increment.as_secs() * (TIME_EXTENT_VAL.amount), + TimeExtentBase::from_millis(2).as_nanos().try_into().unwrap() + ) + ); + + assert_eq!( + TimeExtent::new(&TimeExtentBase::from_secs(1), &(u64::MAX - 1)) + .total_next() + .unwrap() + .unwrap(), + TimeExtentProduct::from_secs(u64::MAX) + ); + } - #[test] - fn it_should_return_none() { - assert_eq!(DefaultTimeExtentMaker::now(&TimeExtentBase::ZERO), None); - } + #[test] + fn it_should_fail_when_too_large() { + assert_eq!(MAX.total_next(), None); + } - #[test] - fn it_should_return_tryfrom_int_error() { - DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); - assert_eq!( - DefaultTimeExtentMaker::now(&TimeExtentBase::from_millis(1)) - .unwrap() - .unwrap_err(), - u64::try_from(u128::MAX).unwrap_err() - ); + #[test] + fn it_should_fail_when_product_is_too_large() { + let time_extent = TimeExtent { + increment: MAX.increment, + amount: 2, + }; + assert_eq!( + time_extent.total_next().unwrap().unwrap_err(), + u64::try_from(u128::MAX).unwrap_err() + ); + } } } - mod make_time_extent_now_after { - use std::time::Duration; - + mod make_time_extent { use super::*; - #[test] - fn it_should_return_a_time_extent() { - assert_eq!( - DefaultTimeExtentMaker::now_after(&TIME_EXTENT_VAL.increment, &Duration::from_secs(TIME_EXTENT_VAL.amount * 2)) - .unwrap() - .unwrap(), - TIME_EXTENT_VAL - ); - } + mod fn_now { + use super::*; + + #[test] + fn it_should_give_a_time_extent() { + assert_eq!( + DefaultTimeExtentMaker::now(&TIME_EXTENT_VAL.increment).unwrap().unwrap(), + TimeExtent { + increment: TIME_EXTENT_VAL.increment, + amount: 0 + } + ); + + DefaultClock::local_set(&DurationSinceUnixEpoch::from_secs(TIME_EXTENT_VAL.amount * 2)); + + assert_eq!( + DefaultTimeExtentMaker::now(&TIME_EXTENT_VAL.increment).unwrap().unwrap(), + TIME_EXTENT_VAL + ); + } - #[test] - fn it_should_return_none() { - assert_eq!( - DefaultTimeExtentMaker::now_after(&TimeExtentBase::ZERO, &Duration::ZERO), - None - ); + #[test] + fn it_should_fail_for_zero() { + assert_eq!(DefaultTimeExtentMaker::now(&TimeExtentBase::ZERO), None); + } - DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); - assert_eq!(DefaultTimeExtentMaker::now_after(&TimeExtentBase::ZERO, &Duration::MAX), None); + #[test] + fn it_should_fail_if_amount_exceeds_bounds() { + DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); + assert_eq!( + DefaultTimeExtentMaker::now(&TimeExtentBase::from_millis(1)) + .unwrap() + .unwrap_err(), + u64::try_from(u128::MAX).unwrap_err() + ); + } } - #[test] - fn it_should_return_tryfrom_int_error() { - DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); - assert_eq!( - DefaultTimeExtentMaker::now_after(&TimeExtentBase::from_millis(1), &Duration::ZERO) + mod fn_now_after { + use std::time::Duration; + + use super::*; + + #[test] + fn it_should_give_a_time_extent() { + assert_eq!( + DefaultTimeExtentMaker::now_after( + &TIME_EXTENT_VAL.increment, + &Duration::from_secs(TIME_EXTENT_VAL.amount * 2) + ) .unwrap() - .unwrap_err(), - u64::try_from(u128::MAX).unwrap_err() - ); - } - } - mod make_time_extent_now_before { - use std::time::Duration; + .unwrap(), + TIME_EXTENT_VAL + ); + } - use super::*; + #[test] + fn it_should_fail_for_zero() { + assert_eq!( + DefaultTimeExtentMaker::now_after(&TimeExtentBase::ZERO, &Duration::ZERO), + None + ); - #[test] - fn it_should_return_a_time_extent() { - DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); + DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); + assert_eq!(DefaultTimeExtentMaker::now_after(&TimeExtentBase::ZERO, &Duration::MAX), None); + } - assert_eq!( - DefaultTimeExtentMaker::now_before( - &TimeExtentBase::from_secs(u32::MAX as u64), - &Duration::from_secs(u32::MAX as u64) - ) - .unwrap() - .unwrap(), - TimeExtent { - increment: TimeExtentBase::from_secs(u32::MAX as u64), - amount: 4294967296 - } - ); + #[test] + fn it_should_fail_if_amount_exceeds_bounds() { + DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); + assert_eq!( + DefaultTimeExtentMaker::now_after(&TimeExtentBase::from_millis(1), &Duration::ZERO) + .unwrap() + .unwrap_err(), + u64::try_from(u128::MAX).unwrap_err() + ); + } } + mod fn_now_before { + use std::time::Duration; - #[test] - fn it_should_return_none() { - assert_eq!( - DefaultTimeExtentMaker::now_before(&TimeExtentBase::ZERO, &Duration::ZERO), - None - ); + use super::*; - assert_eq!( - DefaultTimeExtentMaker::now_before(&TimeExtentBase::ZERO, &Duration::MAX), - None - ); - } + #[test] + fn it_should_give_a_time_extent() { + DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); - #[test] - fn it_should_return_tryfrom_int_error() { - DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); - assert_eq!( - DefaultTimeExtentMaker::now_before(&TimeExtentBase::from_millis(1), &Duration::ZERO) + assert_eq!( + DefaultTimeExtentMaker::now_before( + &TimeExtentBase::from_secs(u32::MAX as u64), + &Duration::from_secs(u32::MAX as u64) + ) .unwrap() - .unwrap_err(), - u64::try_from(u128::MAX).unwrap_err() - ); + .unwrap(), + TimeExtent { + increment: TimeExtentBase::from_secs(u32::MAX as u64), + amount: 4294967296 + } + ); + } + + #[test] + fn it_should_fail_for_zero() { + assert_eq!( + DefaultTimeExtentMaker::now_before(&TimeExtentBase::ZERO, &Duration::ZERO), + None + ); + + assert_eq!( + DefaultTimeExtentMaker::now_before(&TimeExtentBase::ZERO, &Duration::MAX), + None + ); + } + + #[test] + fn it_should_fail_if_amount_exceeds_bounds() { + DefaultClock::local_set(&DurationSinceUnixEpoch::MAX); + assert_eq!( + DefaultTimeExtentMaker::now_before(&TimeExtentBase::from_millis(1), &Duration::ZERO) + .unwrap() + .unwrap_err(), + u64::try_from(u128::MAX).unwrap_err() + ); + } } } }