Rename slot-clock -> slock_clock

This commit is contained in:
Paul Hauner 2018-12-30 13:02:44 +11:00
parent 0ba9b86e87
commit 31c78b7718
No known key found for this signature in database
GPG Key ID: 303E4494BB28068C
5 changed files with 190 additions and 75 deletions

View File

@ -1,74 +0,0 @@
use std::time::{Duration, SystemTime, SystemTimeError};
pub fn slot_now(
genesis_seconds: u64,
slot_duration_seconds: u64,
) -> Result<Option<u64>, SystemTimeError> {
let sys_time = SystemTime::now();
let duration_since_epoch = sys_time.duration_since(SystemTime::UNIX_EPOCH)?;
let duration_since_genesis =
duration_since_epoch.checked_sub(Duration::from_secs(genesis_seconds));
match duration_since_genesis {
None => Ok(None),
Some(d) => Ok(slot_from_duration(slot_duration_seconds, d)),
}
}
fn slot_from_duration(slot_duration_seconds: u64, duration: Duration) -> Option<u64> {
duration.as_secs().checked_div(slot_duration_seconds)
}
#[cfg(test)]
mod tests {
use super::*;
/*
* Note: these tests are using actual system times and could fail if they are executed on a
* very slow machine.
*/
#[test]
fn test_slot_now() {
let s_time = 100;
let now = SystemTime::now();
let since_epoch = now.duration_since(SystemTime::UNIX_EPOCH).unwrap();
let genesis = since_epoch.as_secs() - s_time * 89;
assert_eq!(slot_now(genesis, s_time).unwrap(), Some(89));
let genesis = since_epoch.as_secs();
assert_eq!(slot_now(genesis, s_time).unwrap(), Some(0));
let genesis = since_epoch.as_secs() - s_time * 42 - 5;
assert_eq!(slot_now(genesis, s_time).unwrap(), Some(42));
}
#[test]
fn test_slot_from_duration() {
let s_time = 100;
assert_eq!(slot_from_duration(s_time, Duration::from_secs(0)), Some(0));
assert_eq!(slot_from_duration(s_time, Duration::from_secs(10)), Some(0));
assert_eq!(
slot_from_duration(s_time, Duration::from_secs(100)),
Some(1)
);
assert_eq!(
slot_from_duration(s_time, Duration::from_secs(101)),
Some(1)
);
assert_eq!(
slot_from_duration(s_time, Duration::from_secs(1000)),
Some(10)
);
}
#[test]
fn test_slot_from_duration_slot_time_zero() {
let s_time = 0;
assert_eq!(slot_from_duration(s_time, Duration::from_secs(0)), None);
assert_eq!(slot_from_duration(s_time, Duration::from_secs(10)), None);
assert_eq!(slot_from_duration(s_time, Duration::from_secs(1000)), None);
}
}

View File

@ -1,5 +1,5 @@
[package]
name = "slot-clock"
name = "slot_clock"
version = "0.1.0"
authors = ["Paul Hauner <paul@paulhauner.com>"]
edition = "2018"

View File

@ -0,0 +1,11 @@
mod system_time_slot_clock;
mod testing_slot_clock;
pub use crate::system_time_slot_clock::{Error as SystemTimeSlotClockError, SystemTimeSlotClock};
pub use crate::testing_slot_clock::{Error as TestingSlotClockError, TestingSlotClock};
pub trait SlotClock {
type Error;
fn present_slot(&self) -> Result<Option<u64>, Self::Error>;
}

View File

@ -0,0 +1,135 @@
use super::SlotClock;
use std::time::{Duration, SystemTime};
pub use std::time::SystemTimeError;
#[derive(Debug)]
pub enum Error {
SlotDurationIsZero,
SystemTimeError(SystemTimeError),
}
/// Determines the present slot based upon the present system time.
pub struct SystemTimeSlotClock {
genesis_seconds: u64,
slot_duration_seconds: u64,
}
impl SystemTimeSlotClock {
/// Create a new `SystemTimeSlotClock`.
///
/// Returns an Error if `slot_duration_seconds == 0`.
pub fn new(
genesis_seconds: u64,
slot_duration_seconds: u64,
) -> Result<SystemTimeSlotClock, Error> {
if slot_duration_seconds == 0 {
Err(Error::SlotDurationIsZero)
} else {
Ok(SystemTimeSlotClock {
genesis_seconds,
slot_duration_seconds,
})
}
}
}
impl SlotClock for SystemTimeSlotClock {
type Error = Error;
fn present_slot(&self) -> Result<Option<u64>, Error> {
let syslot_time = SystemTime::now();
let duration_since_epoch = syslot_time.duration_since(SystemTime::UNIX_EPOCH)?;
let duration_since_genesis =
duration_since_epoch.checked_sub(Duration::from_secs(self.genesis_seconds));
match duration_since_genesis {
None => Ok(None),
Some(d) => Ok(slot_from_duration(self.slot_duration_seconds, d)),
}
}
}
impl From<SystemTimeError> for Error {
fn from(e: SystemTimeError) -> Error {
Error::SystemTimeError(e)
}
}
fn slot_from_duration(slot_duration_seconds: u64, duration: Duration) -> Option<u64> {
duration.as_secs().checked_div(slot_duration_seconds)
}
#[cfg(test)]
mod tests {
use super::*;
/*
* Note: these tests are using actual system times and could fail if they are executed on a
* very slow machine.
*/
#[test]
fn test_slot_now() {
let slot_time = 100;
let now = SystemTime::now();
let since_epoch = now.duration_since(SystemTime::UNIX_EPOCH).unwrap();
let genesis = since_epoch.as_secs() - slot_time * 89;
let clock = SystemTimeSlotClock {
genesis_seconds: genesis,
slot_duration_seconds: slot_time,
};
assert_eq!(clock.present_slot().unwrap(), Some(89));
let clock = SystemTimeSlotClock {
genesis_seconds: since_epoch.as_secs(),
slot_duration_seconds: slot_time,
};
assert_eq!(clock.present_slot().unwrap(), Some(0));
let clock = SystemTimeSlotClock {
genesis_seconds: since_epoch.as_secs() - slot_time * 42 - 5,
slot_duration_seconds: slot_time,
};
assert_eq!(clock.present_slot().unwrap(), Some(42));
}
#[test]
fn test_slot_from_duration() {
let slot_time = 100;
assert_eq!(
slot_from_duration(slot_time, Duration::from_secs(0)),
Some(0)
);
assert_eq!(
slot_from_duration(slot_time, Duration::from_secs(10)),
Some(0)
);
assert_eq!(
slot_from_duration(slot_time, Duration::from_secs(100)),
Some(1)
);
assert_eq!(
slot_from_duration(slot_time, Duration::from_secs(101)),
Some(1)
);
assert_eq!(
slot_from_duration(slot_time, Duration::from_secs(1000)),
Some(10)
);
}
#[test]
fn test_slot_from_duration_slot_time_zero() {
let slot_time = 0;
assert_eq!(slot_from_duration(slot_time, Duration::from_secs(0)), None);
assert_eq!(slot_from_duration(slot_time, Duration::from_secs(10)), None);
assert_eq!(
slot_from_duration(slot_time, Duration::from_secs(1000)),
None
);
}
}

View File

@ -0,0 +1,43 @@
use super::SlotClock;
#[derive(Debug, PartialEq)]
pub enum Error {}
/// Determines the present slot based upon the present system time.
pub struct TestingSlotClock {
slot: u64,
}
impl TestingSlotClock {
/// Create a new `TestingSlotClock`.
///
/// Returns an Error if `slot_duration_seconds == 0`.
pub fn new(slot: u64) -> TestingSlotClock {
TestingSlotClock { slot }
}
pub fn set_slot(&mut self, slot: u64) {
self.slot = slot;
}
}
impl SlotClock for TestingSlotClock {
type Error = Error;
fn present_slot(&self) -> Result<Option<u64>, Error> {
Ok(Some(self.slot))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_slot_now() {
let mut clock = TestingSlotClock::new(10);
assert_eq!(clock.present_slot(), Ok(Some(10)));
clock.set_slot(123);
assert_eq!(clock.present_slot(), Ok(Some(123)));
}
}