1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*! # mock_instant
**_NOTE_** As of verison 0.6, the timer resolution is nanosecond-based, which may be much more accurate than the real thing
**_NOTE_** As of version 0.5. MockClock/Instant/SystemTime have been moved to specific modules
**_NOTE_** The modules, `global` and `thread_local` change the behavior across threads. If `global` is used, the clock keeps its state across threads, otherwise if `thread_local` is used, a new *source* is made for each thread
To ensure unsurprising behavior, **reset** the clock _before_ each test (if that behavior is applicable.)
---
This crate allows you to test `Instant`/`Duration`/`SystemTime` code, deterministically.
It provides a replacement `std::time::Instant` that uses a deterministic 'clock'
You can swap out the `std::time::Instant` with this one by doing something similar to:
```rust
#[cfg(test)]
use mock_instant::global::Instant;
#[cfg(not(test))]
use std::time::Instant;
```
or for a `std::time::SystemTime`
```rust
#[cfg(test)]
use mock_instant::global::{SystemTime, SystemTimeError};
#[cfg(not(test))]
use std::time::{SystemTime, SystemTimeError};
```
```rust
use mock_instant::global::{MockClock, Instant};
use std::time::Duration;
let now = Instant::now();
MockClock::advance(Duration::from_secs(15));
MockClock::advance(Duration::from_secs(2));
// its been '17' seconds
assert_eq!(now.elapsed(), Duration::from_secs(17));
```
## API:
```rust,compile_fail
// Overrides the current time to this `Duration`
MockClock::set_time(time: Duration)
// Advance the current time by this `Duration`
MockClock::advance(time: Duration)
// Get the current time
MockClock::time() -> Duration
// Overrides the current `SystemTime` to this duration
MockClock::set_system_time(time: Duration)
// Advance the current `SystemTime` by this duration
MockClock::advance_system_time(time: Duration)
// Get the current `SystemTime`
MockClock::system_time() -> Duration
// Determine if this MockClock was thread-local: (useful for assertions to ensure the right mode is being used)
MockClock::is_thread_local() -> bool
Instant::now().is_thread_local() -> bool
SystemTime::now().is_thread_local() -> bool
```
## Usage:
**_NOTE_** The clock starts at `Duration::ZERO`
In your tests, you can use `MockClock::set_time(Duration::ZERO)` to reset the clock back to 0. Or, you can set it to some sentinel time value.
Then, before you check your time-based logic, you can advance the clock by some `Duration` (it'll freeze the time to that duration)
You can also get the current frozen time with `MockClock::time`
`SystemTime` is also mockable with a similar API.
## Thread-safety:
Two modes are provided via modules. The APIs are identical but the `MockClock` source has different behavior in different threads.
- `mock_instant::global`
- `MockClock` will have a new state per thread
- `Instant`will have a new state per thread
- `SystemTime` will have a new state per thread
- `mock_instant::thread_local`
- `MockClock` will have a new state per thread
- `Instant`will have a new state per thread
- `SystemTime` will have a new state per thread
*/
use Duration;
/// An error returned from the duration_since and elapsed methods on SystemTime, used to learn how far in the opposite direction a system time lies.
;
/// Thread-local state.
///
/// This creates a new state when accessed from a new thread
/// Global state.
///
/// This shares its 'clock' across threads