Expand description
Provides a method unix_time
which returns elapsed time since UNIX EPOCH. The returned time
can be faked in each thread separately.
Compilation Time Switch
Faketime can be disabled at compilation time to avoid runtime overhead and potential vulnerability of manipulating the process time.
It is disabled via rust cfg disable_faketime
, e.g.:
RUSTFLAGS="--cfg disable_faketime" cargo build
By default, without setting the cfg, faketime is available for all the threads.
Usage
The faketime setting is per thread. If it is enabled in a thread, a file path is also configured. The file should store the milliseconds since UNIX EPOCH. This function will first try to read the time from this file, and fallback to the system time when an error occurs.
The most straightforward way to enable faketime is calling faketime::enable(path)
in the
thread, and path
is the configured timestamp file. It also overrides the auto-detected
settings, as mentioned below.
assert_ne!(faketime::unix_time().as_secs(), 100);
let _faketime_file = faketime::enable_and_write_millis(100_000).expect("enable faketime");
assert_eq!(faketime::unix_time().as_secs(), 100);
In each thread, when this function is first invoked, and neither faketime::enable(path)
nor
faketime::disable()
has been invoked in the thread already, it will detect whether faketime
should be enabled and which timestamp file should be used.
First, if the environment variable FAKETIME_DIR
exists, and this thread has a name
THREAD_NAME
(see std::thread::Thread::name
), faketime is enabled, and the timestamp file
path is FAKETIME_DIR/THREAD_NAME
.
use std::env;
use std::fs;
use std::thread;
use tempfile::TempDir;
let dir = TempDir::new().expect("create temp dir");
env::set_var("FAKETIME_DIR", dir.path().as_os_str());
let file = dir.path().join("faketime");
faketime::write_millis(&file, 123_456);
thread::Builder::new()
.name("faketime".to_string())
.spawn(|| assert_eq!(123, faketime::unix_time().as_secs()))
.expect("spawn thread")
.join()
.expect("join thread");
If the environment variable FAKETIME_DIR
is missing, but this thread has a name and the name
starts with FAKETIME=
literally, faketime is also enabled, and the timestamp file is the
portion of the thread name after FAKETIME=
.
use std::fs;
use std::thread;
use tempfile::NamedTempFile;
let file = NamedTempFile::new().expect("create temp file");
faketime::write_millis(file.path(), 123_456);
thread::Builder::new()
.name(format!("FAKETIME={}", file.path().display()))
.spawn(|| assert_eq!(123, faketime::unix_time().as_secs()))
.expect("spawn thread")
.join()
.expect("join thread");
Otherwise, faketime is disabled in the thread, until it is manually enabled via
faketime::enable(path)
.
use std::thread;
let start = faketime::system::unix_time();
thread::spawn(move || assert!((faketime::unix_time() - start).as_secs() < 60))
.join()
.expect("spawn thread");
Atomic Write
This function reads timestamp from the file when faketime is enabled. To ensure the written
content is read in a whole, it is recommended to write the file atomically. One solution is
writing to a temporary file and then moving to the target path, as implemented in
faketime::write_millis(path, millis)
.
Following snippet demonstrates how to write time to file /tmp/faketime.
cat 100 > /tmp/faketime_
mv /tmp/faketime_ /tmp/faketime