From 3d469e138340b7743f5a0695059b2b163edb149e Mon Sep 17 00:00:00 2001 From: Guillaume Leroy Date: Tue, 19 Sep 2023 17:01:03 +0200 Subject: [PATCH] feat: add clock --- Cargo.toml | 3 +++ src/clock.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 8 ++++++ 3 files changed, 81 insertions(+) create mode 100644 src/clock.rs diff --git a/Cargo.toml b/Cargo.toml index dd83e83..9d738a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,10 @@ keywords = ["mock", "mockable", "mocking", "test"] categories = ["development-tools::testing"] [features] +clock = ["dep:chrono"] +full = ["clock"] mock = ["dep:mockall"] [dependencies] +chrono = { version = "0.4", optional = true } mockall = { version = "0.11", optional = true } diff --git a/src/clock.rs b/src/clock.rs new file mode 100644 index 0000000..9b57cde --- /dev/null +++ b/src/clock.rs @@ -0,0 +1,70 @@ +use chrono::{DateTime, Local, Utc}; +use mockall::mock; + +// Clock + +/// A trait for getting the current time. +/// +/// **This is supported on `feature=clock` only.** +/// # Examples +/// +/// ``` +/// use chrono::{DateTime, Utc, Duration}; +/// use mockable::{Clock, DefaultClock, MockClock}; +/// +/// fn now(clock: &dyn Clock) -> DateTime { +/// clock.utc() +/// } +/// +/// // Default +/// let time = now(&DefaultClock); +/// assert!(time < Utc::now() + Duration::seconds(1)); +/// +/// // Mock +/// let expected = Utc::now(); +/// let mut clock = MockClock::new(); +/// clock +/// .expect_utc() +/// .returning(move || expected); +/// let time = now(&clock); +/// assert_eq!(time, expected); +/// ``` +pub trait Clock: Send + Sync { + /// Returns the current time in the local timezone. + fn local(&self) -> DateTime; + + /// Returns the current time in UTC. + fn utc(&self) -> DateTime; +} + +// DefaultClock + +/// Default implementation of `Clock`. +/// +/// **This is supported on `feature=clock` only.** +pub struct DefaultClock; + +impl Clock for DefaultClock { + fn local(&self) -> DateTime { + Local::now() + } + + fn utc(&self) -> DateTime { + Utc::now() + } +} + +// MockClock + +#[cfg(feature = "mock")] +mock! { + /// `mockall` implementation of `Clock`. + /// + /// **This is supported on `feature=clock,mock` only.** + pub Clock {} + + impl super::Clock for Clock { + fn local(&self) -> DateTime; + fn utc(&self) -> DateTime; + } +} diff --git a/src/lib.rs b/src/lib.rs index 8b13789..92568d9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,9 @@ +// Re-use +#[cfg(feature = "clock")] +pub use self::clock::*; + +// Mods + +#[cfg(feature = "clock")] +mod clock;