Rust时间模拟库sn_fake_clock的使用,轻松实现测试环境中的时间控制和模拟
Rust时间模拟库sn_fake_clock的使用,轻松实现测试环境中的时间控制和模拟
概述
sn_fake_clock提供了一个FakeClock
结构体,它模仿了std::time::Instant
的接口,并能在测试期间完全控制代码感知到的时间流。
安装
在项目目录中运行以下Cargo命令:
cargo add sn_fake_clock
或者在Cargo.toml中添加以下行:
sn_fake_clock = "0.4.14"
使用示例
下面是一个完整的示例demo,展示如何使用sn_fake_clock来模拟和控制时间:
use sn_fake_clock::FakeClock;
use std::time::Duration;
#[test]
fn test_time_control() {
// 初始化假时钟
FakeClock::set_time(0);
// 获取当前时间
let start = FakeClock::now();
assert_eq!(start.elapsed(), Duration::from_secs(0));
// 向前推进时间
FakeClock::advance_time(Duration::from_secs(10));
// 验证时间确实前进了
assert_eq(start.elapsed(), Duration::from_secs(10));
// 设置特定时间点
FakeClock::set_time(100);
assert_eq(FakeClock::now().elapsed(), Duration::from_secs(100));
}
#[test]
fn test_time_dependent_logic() {
FakeClock::set_time(0);
let start = FakeClock::now();
// 模拟需要等待的逻辑
FakeClock::advance_time(Duration::from_millis(500));
// 验证经过的时间
let elapsed = start.elapsed();
assert!(elapsed >= Duration::from_millis(500));
assert!(elapsed < Duration::from_millis(501));
}
完整示例
use sn_fake_clock::FakeClock;
use std::time::Duration;
use std::thread;
// 测试时间控制功能
#[test]
fn test_clock_operations() {
// 初始化时间为0
FakeClock::set_time(0);
// 验证初始时间
let now = FakeClock::now();
assert_eq!(now.elapsed(), Duration::from_secs(0));
// 前进5秒
FakeClock::advance_time(Duration::from_secs(5));
assert_eq!(now.elapsed(), Duration::from_secs(5));
// 前进500毫秒
FakeClock::advance_time(Duration::from_millis(500));
assert_eq!(now.elapsed(), Duration::from_millis(5500));
// 直接设置时间为10秒
FakeClock::set_time(10_000);
assert_eq!(FakeClock::now().elapsed(), Duration::from_millis(10_000));
}
// 测试时间敏感逻辑
#[test]
fn test_time_sensitive_operations() {
FakeClock::set_time(0);
// 记录开始时间
let start = FakeClock::now();
// 模拟耗时操作
FakeClock::advance_time(Duration::from_secs(3));
// 检查耗时
assert_eq!(start.elapsed(), Duration::from_secs(3));
// 模拟短时间等待
FakeClock::advance_time(Duration::from_millis(250));
assert_eq!(start.elapsed(), Duration::from_millis(3250));
}
// 测试定时器功能
#[test]
fn test_timer_functionality() {
FakeClock::set_time(0);
let timer_start = FakeClock::now();
// 模拟定时器超时(1秒后)
FakeClock::advance_time(Duration::from_secs(1));
// 检查是否超时
assert!(timer_start.elapsed() >= Duration::from_secs(1));
assert!(timer_start.elapsed() < Duration::from_secs(2));
// 再前进500毫秒
FakeClock::advance_time(Duration::from_millis(500));
assert_eq!(timer_start.elapsed(), Duration::from_millis(1500));
}
主要功能
- 设置特定时间点:使用
FakeClock::set_time
可以直接设置时钟到特定时间 - 前进时间:使用
FakeClock::advance_time
可以模拟时间的流逝 - 获取当前时间:
FakeClock::now()
返回一个类似Instant
的对象,可以测量时间间隔
许可证
这个SAFE Network库采用双重许可:
- 修改后的BSD许可证
- MIT许可证
您可以选择其中一种。
贡献
欢迎贡献!无论是编写新代码、修复bug还是报告错误,所有形式的贡献都受到鼓励。
1 回复
Rust时间模拟库sn_fake_clock使用指南
简介
sn_fake_clock是一个Rust库,专门用于在测试环境中模拟和控制时间。它允许开发者在不修改系统时间的情况下,创建可控的时间环境,这对于需要测试时间相关逻辑的应用程序特别有用。
主要特性
- 模拟系统时间而不影响真实系统时钟
- 支持时间跳转(向前或向后)
- 线程安全的时间控制
- 易于集成到现有测试框架中
安装
在Cargo.toml中添加依赖:
[dependencies]
sn_fake_clock = "0.1"
完整示例代码
下面是一个完整的测试用例,展示了sn_fake_clock的主要功能:
use sn_fake_clock::FakeClock;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
// 测试基本时间模拟功能
#[test]
fn test_fake_clock_basic() {
// 1. 基础时间模拟
let mut clock = FakeClock::from_millis(1609459200000); // 2021-01-01 00:00:00 UTC
assert_eq!(clock.now_millis(), 1609459200000);
// 2. 时间跳转测试
// 向前跳转1天
clock.advance(Duration::from_secs(86400));
assert_eq!(clock.now_millis(), 1609459200000 + 86400*1000);
// 向后跳转12小时
clock.rewind(Duration::from_secs(43200));
assert_eq!(clock.now_millis(), 1609459200000 + 43200*1000);
}
// 测试全局时间冻结功能
#[test]
fn test_global_time_freeze() {
// 冻结全局时间为特定时间点
let _guard = FakeClock::freeze_at_millis(1609459200000); // 2021-01-01 00:00:00
// 获取当前时间戳的函数
fn current_timestamp() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
}
// 验证时间是否正确冻结
assert_eq!(current_timestamp(), 1609459200);
// 全局时间跳转1小时
FakeClock::advance(Duration::from_secs(3600));
assert_eq!(current_timestamp(), 1609459200 + 3600);
}
// 测试自动时间递增功能
#[test]
fn test_auto_advance() {
let mut clock = FakeClock::from_millis(1609459200000);
// 设置自动递增速率:真实1秒 = 模拟1分钟
clock.set_auto_advance_rate(60.0);
let start = clock.now_millis();
std::thread::sleep(Duration::from_secs(1));
let end = clock.now_millis();
// 验证时间是否自动增加了约60秒
let diff = end - start;
assert!(diff >= 60_000 && diff <= 61_000, "实际增加时间: {}ms", diff);
}
// 测试超时逻辑
#[test]
fn test_complex_timeout() {
let _guard = FakeClock::freeze_at_millis(1609459200000);
let start_time = 1609459200; // 2021-01-01 00:00:00
// 超时检查函数
fn is_timeout(start: u64, timeout_secs: u64) -> bool {
let current = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
current - start >= timeout_secs
}
// 测试不同时间点的超时状态
let test_cases = vec![
(0, false), // 刚开始
(59, false), // 差1秒超时
(60, true), // 刚好超时
(120, true), // 超时很久
];
for (advance_secs, expected) in test_cases {
FakeClock::rewind(Duration::from_secs(3600)); // 重置时间
FakeClock::advance(Duration::from_secs(advance_secs));
assert_eq!(
is_timeout(start_time, 60),
expected,
"前进{}秒后超时状态应为{}",
advance_secs,
expected
);
}
}
注意事项
- 在测试完成后,确保释放时间模拟,以免影响其他测试
- 对于多线程测试,确保时间操作是线程安全的
- 不要在生产环境中使用这个库,它仅用于测试目的
这个完整示例展示了sn_fake_clock的主要功能,包括基础时间模拟、时间跳转、全局时间冻结、自动时间递增和超时逻辑测试。你可以根据实际测试需求调整这些示例代码。