Module faketime::faketime

source ·
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

Functions

Disables faketime in current thread.
Enables faketime in current thread and use the specified timestamp file.
Enables and writes time into the timestamp file.
Gets elapsed time since UNIX EPOCH.
Writes time as milliseconds since UNIX EPOCH into the specified timestamp file.

Type Definitions

A specialized Result type for I/O operations.