Last active
December 27, 2022 10:28
-
-
Save eval-exec/177bffa02bdb0302e1d59c94266508d9 to your computer and use it in GitHub Desktop.
faketime issue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use serial_test::serial; | |
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; | |
// Store faketime timestamp here | |
#[cfg(test)] | |
static FAKETIME: AtomicU64 = AtomicU64::new(0); | |
// Indicate whether faketime is enabled | |
#[cfg(test)] | |
static ENABLE_FAKETIME: AtomicBool = AtomicBool::new(false); | |
// Get real system's timestamp in millis | |
fn system_time_as_millis() -> u64 { | |
let duration = std::time::SystemTime::now() | |
.duration_since(std::time::SystemTime::UNIX_EPOCH) | |
.expect("SystemTime before UNIX EPOCH!"); | |
duration.as_secs() * 1000 + u64::from(duration.subsec_millis()) | |
} | |
/// SystemTime provide methods to get system's timestamp in millis | |
/// | |
/// If use it in test module, it provide FaketimeGuard to enable/disable/set faketime | |
pub struct SystemTime {} | |
impl SystemTime { | |
#[cfg(not(test))] | |
pub fn unix_time_as_millis() -> u64 { | |
system_time_as_millis() | |
} | |
#[cfg(test)] | |
pub fn faketime() -> FaketimeGuard { | |
FaketimeGuard {} | |
} | |
#[cfg(test)] | |
pub fn unix_time_as_millis() -> u64 { | |
if ENABLE_FAKETIME.load(Ordering::SeqCst) { | |
return FAKETIME.load(Ordering::SeqCst); | |
} | |
system_time_as_millis() | |
} | |
} | |
#[cfg(test)] | |
pub struct FaketimeGuard {} | |
#[cfg(test)] | |
impl FaketimeGuard { | |
#[cfg(test)] | |
fn set_faketime(&self, time: u64) { | |
FAKETIME.store(time, Ordering::Relaxed); | |
ENABLE_FAKETIME.store(true, Ordering::SeqCst); | |
} | |
#[cfg(test)] | |
fn disable_faketime(&self) { | |
ENABLE_FAKETIME.store(false, Ordering::Relaxed); | |
} | |
} | |
#[cfg(test)] | |
impl Drop for FaketimeGuard { | |
fn drop(&mut self) { | |
self.disable_faketime() | |
} | |
} | |
///////////// main /////////////////// | |
fn main() { | |
dbg!(SystemTime::unix_time_as_millis()); | |
// bellow line won't compile, | |
// because SystemTime::faketime() only exists in the test module | |
// let x = SystemTime::faketime(); | |
} | |
///////////// test /////////////////// | |
#[serial] | |
#[test] | |
fn test0() { | |
let faketime_guard = SystemTime::faketime(); | |
faketime_guard.set_faketime(123); | |
assert!(SystemTime::unix_time_as_millis() == 123); | |
faketime_guard.set_faketime(100); | |
assert!(SystemTime::unix_time_as_millis() == 100); | |
faketime_guard.disable_faketime(); | |
let now = system_time_as_millis(); | |
assert!(SystemTime::unix_time_as_millis() >= now); | |
// The faketime_guard was dropped at the end of the scope, | |
// then ENABLE_FAKETIME will be set to false | |
} | |
#[serial] | |
#[test] | |
fn test1() { | |
let now = system_time_as_millis(); | |
assert!(SystemTime::unix_time_as_millis() >= now); | |
} | |
#[serial] | |
#[test] | |
fn test2() { | |
let now = system_time_as_millis(); | |
{ | |
let faketime_guard = SystemTime::faketime(); | |
faketime_guard.set_faketime(1); | |
assert!(SystemTime::unix_time_as_millis() == 1); | |
} | |
assert!(SystemTime::unix_time_as_millis() >= now); | |
{ | |
let faketime_guard = SystemTime::faketime(); | |
faketime_guard.set_faketime(2); | |
assert!(SystemTime::unix_time_as_millis() == 2); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment