• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Utility file to provide a fake clock object representing current time, and a timerfd driven by
6 // that time.
7 
8 use std::{
9     os::unix::io::AsRawFd,
10     time::{Duration, Instant},
11 };
12 
13 use super::EventFd;
14 
15 #[derive(Debug, Copy, Clone)]
16 pub struct Clock(Instant);
17 impl Clock {
new() -> Self18     pub fn new() -> Self {
19         Clock(Instant::now())
20     }
21 
now(&self) -> Self22     pub fn now(&self) -> Self {
23         Clock(Instant::now())
24     }
25 
duration_since(&self, earlier: &Self) -> Duration26     pub fn duration_since(&self, earlier: &Self) -> Duration {
27         self.0.duration_since(earlier.0)
28     }
29 
elapsed(&self) -> Duration30     pub fn elapsed(&self) -> Duration {
31         self.0.elapsed()
32     }
33 
checked_sub(&self, duration: Duration) -> Option<Self>34     pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
35         Some(Clock(self.0.checked_sub(duration)?))
36     }
37 }
38 
39 impl Default for Clock {
default() -> Self40     fn default() -> Self {
41         Self::new()
42     }
43 }
44 
45 const NS_PER_SEC: u64 = 1_000_000_000;
46 /// A fake clock that can be used in tests to give exact control over the time.
47 /// For a code example, see the tests in sys_util/src/timerfd.rs.
48 #[derive(Debug)]
49 pub struct FakeClock {
50     ns_since_epoch: u64,
51     deadlines: Vec<(u64, EventFd)>,
52 }
53 
54 impl FakeClock {
new() -> Self55     pub fn new() -> Self {
56         FakeClock {
57             ns_since_epoch: 1_547_163_599 * NS_PER_SEC,
58             deadlines: Vec::new(),
59         }
60     }
61 
62     /// Get the current time, according to this clock.
now(&self) -> Self63     pub fn now(&self) -> Self {
64         FakeClock {
65             ns_since_epoch: self.ns_since_epoch,
66             deadlines: Vec::new(),
67         }
68     }
69 
70     ///  Get the current time in ns, according to this clock.
nanos(&self) -> u6471     pub fn nanos(&self) -> u64 {
72         self.ns_since_epoch
73     }
74 
75     /// Get the duration since |earlier|, assuming that earlier < self.
duration_since(&self, earlier: &Self) -> Duration76     pub fn duration_since(&self, earlier: &Self) -> Duration {
77         let ns_diff = self.ns_since_epoch - earlier.ns_since_epoch;
78         Duration::new(ns_diff / NS_PER_SEC, (ns_diff % NS_PER_SEC) as u32)
79     }
80 
81     /// Get the time that has elapsed since this clock was made. Always returns 0 on a FakeClock.
elapsed(&self) -> Duration82     pub fn elapsed(&self) -> Duration {
83         self.now().duration_since(self)
84     }
85 
checked_sub(&self, duration: Duration) -> Option<Self>86     pub fn checked_sub(&self, duration: Duration) -> Option<Self> {
87         Some(FakeClock {
88             ns_since_epoch: self
89                 .ns_since_epoch
90                 .checked_sub(duration.as_nanos() as u64)?,
91             deadlines: Vec::new(),
92         })
93     }
94 
95     /// Register the event fd for a notification when self's time is |deadline_ns|.
96     /// Drop any existing events registered to the same raw fd.
add_event_fd(&mut self, deadline_ns: u64, fd: EventFd)97     pub fn add_event_fd(&mut self, deadline_ns: u64, fd: EventFd) {
98         self.deadlines
99             .retain(|(_, old_fd)| fd.as_raw_fd() != old_fd.as_raw_fd());
100         self.deadlines.push((deadline_ns, fd));
101     }
102 
add_ns(&mut self, ns: u64)103     pub fn add_ns(&mut self, ns: u64) {
104         self.ns_since_epoch += ns;
105         let time = self.ns_since_epoch;
106         self.deadlines.retain(|(ns, fd)| {
107             let expired = *ns <= time;
108             if expired {
109                 fd.write(1).unwrap();
110             }
111             !expired
112         });
113     }
114 }
115 
116 impl Default for FakeClock {
default() -> Self117     fn default() -> Self {
118         Self::new()
119     }
120 }
121