catenis_api_client 3.0.1

Catenis API client library for the Rust programming language
Documentation
use std::{
    sync::Mutex,
    thread::{
        self, ThreadId,
    },
    collections::HashMap,
};
use once_cell::sync::Lazy;
use time::OffsetDateTime;

static CUSTOM_TIME: Lazy<Mutex<HashMap<ThreadId, i64>>> = Lazy::new(|| Mutex::new(HashMap::new()));

pub fn now() -> OffsetDateTime {
    let custom_time = CUSTOM_TIME.lock().unwrap();
    let thread_id = thread::current().id();

    if custom_time.contains_key(&thread_id) {
        OffsetDateTime::from_unix_timestamp(*custom_time.get(&thread_id).unwrap())
    } else {
        OffsetDateTime::now_utc()
    }
}

pub struct CustomTime();

impl CustomTime {
    pub fn set(time: &OffsetDateTime) -> Self {
        let mut custom_time = CUSTOM_TIME.lock().unwrap();

        custom_time.insert(thread::current().id(), time.unix_timestamp());

        CustomTime()
    }
}

impl Drop for CustomTime {
    fn drop(&mut self) {
        let mut custom_time = CUSTOM_TIME.lock().unwrap();

        custom_time.remove(&thread::current().id());
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::thread;

    #[test]
    fn it_get_system_time() {
        let sys_now = OffsetDateTime::now_utc();
        let test_now = now();

        assert!(test_now >= sys_now, "Current test time less than current system time");
        assert!((test_now - sys_now) < std::time::Duration::from_millis(10), "Current test time not within 10 ms from current system time");
    }

    #[test]
    fn it_set_custom_time() {
        let ref_time = time::date!(2020-12-01).with_time(time::time!(06:00:00)).assume_utc();

        let _custom_time = CustomTime::set(&ref_time);

        assert_eq!(now(), ref_time);
    }

    #[test]
    fn it_set_custom_time_thread() {
        let child_thread = thread::spawn(|| {
            let ref_time = time::date!(2020-12-05).with_time(time::time!(08:10:05)).assume_utc();

            let _custom_time = CustomTime::set(&ref_time);

            assert_eq!(now(), ref_time);
        });

        let sys_now = OffsetDateTime::now_utc();
        let test_now = now();

        assert!(test_now >= sys_now, "Current test time less than current system time");
        assert!((test_now - sys_now) < std::time::Duration::from_millis(10), "Current test time not within 10 ms from current system time");

        child_thread.join().unwrap();
    }

    #[test]
    fn it_set_custom_time_two_threads() {
        let child_thread_1 = thread::spawn(|| {
            let ref_time = time::date!(2020-12-10).with_time(time::time!(10:20:10)).assume_utc();

            let _custom_time = CustomTime::set(&ref_time);

            assert_eq!(now(), ref_time);
        });

        let child_thread_2 = thread::spawn(|| {
            let ref_time = time::date!(2020-12-15).with_time(time::time!(12:40:15)).assume_utc();

            let _custom_time = CustomTime::set(&ref_time);

            assert_eq!(now(), ref_time);
        });

        let sys_now = OffsetDateTime::now_utc();
        let test_now = now();

        assert!(test_now >= sys_now, "Current test time less than current system time");
        assert!((test_now - sys_now) < std::time::Duration::from_millis(10), "Current test time not within 10 ms from current system time");

        child_thread_1.join().unwrap();
        child_thread_2.join().unwrap();
    }
}